diff --git a/pygitweb/actions.py b/pygitweb/actions.py
index cd40178..1a958b2 100644
--- a/pygitweb/actions.py
+++ b/pygitweb/actions.py
@@ -60,15 +60,15 @@ def parse_pagination(
 	if page is not None:
 		try:
 			p = int(page)
-		except ValueError:
-			raise HTTPException(status_code=400, detail="page must be an integer")
+		except ValueError as e:
+			raise HTTPException(status_code=400, detail="page must be an integer") from e
 		if p < 1:
 			raise HTTPException(status_code=400, detail="page must be at least 1")
 	if pagecount is not None:
 		try:
 			pc = int(pagecount)
-		except ValueError:
-			raise HTTPException(status_code=400, detail="pagecount must be an integer")
+		except ValueError as e:
+			raise HTTPException(status_code=400, detail="pagecount must be an integer") from e
 		if pc < 1:
 			raise HTTPException(status_code=400, detail="pagecount must be at least 1")
 		if pc > 50:
@@ -218,8 +218,8 @@ def _commit_unified_diff_or_raise(project: str, h: str) -> tuple[str, str]:
 		raise HTTPException(status_code=400, detail="Invalid ref or hash")
 	try:
 		return get_commit_unified_diff(project, h)
-	except (KeyError, pygit2.GitError, OSError, ValueError):
-		raise HTTPException(status_code=404, detail="Commit not found")
+	except (KeyError, pygit2.GitError, OSError, ValueError) as e:
+		raise HTTPException(status_code=404, detail="Commit not found") from e
 
 
 # ---------- Action handlers ----------
@@ -244,8 +244,8 @@ def git_object(project: str, h: str | None) -> Response:
 		try:
 			repo = open_repo(project)
 			obj = repo.revparse_single(h)
-		except (KeyError, pygit2.GitError, OSError):
-			raise HTTPException(status_code=404, detail="Object not found")
+		except (KeyError, pygit2.GitError, OSError) as e:
+			raise HTTPException(status_code=404, detail="Object not found") from e
 		if not isinstance(obj, pygit2.Blob):
 			raise HTTPException(status_code=404, detail="Not a blob")
 		data = obj.data
@@ -537,8 +537,8 @@ def git_tags(project: str, request: Request, page: int, pagecount: int) -> HTMLR
 	tags_page = tags_list[skip : skip + pagecount]
 	try:
 		repo = open_repo(project)
-	except Exception:
-		raise HTTPException(status_code=404, detail="Repository not found")
+	except Exception as e:
+		raise HTTPException(status_code=404, detail="Repository not found") from e
 	rows = []
 	for name, _ref, oid in tags_page:
 		tag_link = f"/project/{project}?a=tag&h={quote(oid, safe='')}"
@@ -590,8 +590,8 @@ def git_tag(project: str, h: str | None) -> HTMLResponse:
 	try:
 		repo = open_repo(project)
 		obj = repo.revparse_single(h)
-	except (KeyError, pygit2.GitError, OSError):
-		raise HTTPException(status_code=404, detail="Tag or object not found")
+	except (KeyError, pygit2.GitError, OSError) as e:
+		raise HTTPException(status_code=404, detail="Tag or object not found") from e
 	if not isinstance(obj, pygit2.Tag):
 		raise HTTPException(status_code=404, detail="Not a tag object")
 	tag_oid = str(obj.id)
@@ -647,8 +647,8 @@ def git_commit(project: str, h: str | None) -> HTMLResponse:
 	try:
 		repo = open_repo(project)
 		obj = repo.revparse_single(h)
-	except (KeyError, pygit2.GitError, OSError):
-		raise HTTPException(status_code=404, detail="Commit not found")
+	except (KeyError, pygit2.GitError, OSError) as e:
+		raise HTTPException(status_code=404, detail="Commit not found") from e
 	if not isinstance(obj, pygit2.Commit):
 		raise HTTPException(status_code=404, detail="Not a commit object")
 	commit = obj
diff --git a/pygitweb/main.py b/pygitweb/main.py
index 6f85605..81368a7 100644
--- a/pygitweb/main.py
+++ b/pygitweb/main.py
@@ -164,7 +164,7 @@ async def loadavg_middleware(request: Request, call_next):
 	except RuntimeError as e:
 		msg = str(e)
 		if msg.startswith("503:"):
-			raise HTTPException(status_code=503, detail=msg[4:])
+			raise HTTPException(status_code=503, detail=msg[4:]) from e
 		raise
 	return await call_next(request)
 
@@ -414,11 +414,11 @@ async def addproject_submit(
 		if do_task_board:
 			pass  # stub
 	except pygit2.GitError as e:
-		raise HTTPException(status_code=400, detail=f"Git error: {e}")
+		raise HTTPException(status_code=400, detail=f"Git error: {e}") from e
 	except HTTPException:
 		raise
 	except OSError as e:
-		raise HTTPException(status_code=500, detail=str(e))
+		raise HTTPException(status_code=500, detail=str(e)) from e
 
 	return RedirectResponse(url=f"/project/{project_name}", status_code=303)
 
diff --git a/pygitweb/tasks.py b/pygitweb/tasks.py
index 1b40321..22e3be5 100644
--- a/pygitweb/tasks.py
+++ b/pygitweb/tasks.py
@@ -504,8 +504,8 @@ def comment_delete(
 	oid = pygit2.Oid(hex=comment_oid)
 	try:
 		c = get_comment(repo, oid)
-	except (ValueError, KeyError):
-		raise HTTPException(status_code=404, detail="Comment not found")
+	except (ValueError, KeyError) as e:
+		raise HTTPException(status_code=404, detail="Comment not found") from e
 	if not c:
 		raise HTTPException(status_code=404, detail="Comment not found")
 	return JSONResponse(content={"message": "Comment deleted"})
