From 69ce1df5a181a472edf9132f826da0a4adecef3b Mon Sep 17 00:00:00 2001 From: Pier-Jean Malandrino Date: Fri, 3 Apr 2026 13:48:33 +0200 Subject: [PATCH] Narrow exception handlers for better diagnostics Replace broad `except Exception` with specific types (FileNotFoundError, PermissionError, OSError) so errors are properly categorized in logs. Users reporting bugs will get actionable messages instead of generic ones. --- document-parser/api/documents.py | 7 ++++++- document-parser/services/analysis_service.py | 4 +++- document-parser/services/document_service.py | 13 ++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/document-parser/api/documents.py b/document-parser/api/documents.py index 183546b..a9b1fd0 100644 --- a/document-parser/api/documents.py +++ b/document-parser/api/documents.py @@ -91,6 +91,11 @@ async def preview( return Response(content=png_bytes, media_type="image/png") except ValueError as e: raise HTTPException(status_code=404, detail=str(e)) from e + except FileNotFoundError as exc: + raise HTTPException(status_code=404, detail="PDF file not found on disk") from exc + except OSError as exc: + logger.exception("I/O error generating preview for %s", doc_id) + raise HTTPException(status_code=422, detail="Failed to read PDF file") from exc except Exception as exc: - logger.exception("Failed to generate preview") + logger.exception("Unexpected error generating preview for %s", doc_id) raise HTTPException(status_code=422, detail="Failed to generate preview") from exc diff --git a/document-parser/services/analysis_service.py b/document-parser/services/analysis_service.py index 0f4ea6a..095d05a 100644 --- a/document-parser/services/analysis_service.py +++ b/document-parser/services/analysis_service.py @@ -192,5 +192,7 @@ async def _mark_failed(job_id: str, error: str) -> None: if job: job.mark_failed(error) await analysis_repo.update_status(job) + except OSError: + logger.exception("Database I/O error marking job %s as failed", job_id) except Exception: - logger.exception("Could not mark job %s as failed", job_id) + logger.exception("Unexpected error marking job %s as failed", job_id) diff --git a/document-parser/services/document_service.py b/document-parser/services/document_service.py index fbebfa6..58cf2f3 100644 --- a/document-parser/services/document_service.py +++ b/document-parser/services/document_service.py @@ -79,8 +79,12 @@ async def delete(doc_id: str) -> bool: os.unlink(real_path) elif os.path.exists(doc.storage_path): logger.warning("Refused to delete file outside upload dir: %s", doc.storage_path) + except FileNotFoundError: + logger.info("File already removed: %s", doc.storage_path) + except PermissionError: + logger.error("Permission denied deleting file: %s", doc.storage_path) except OSError: - logger.warning("Could not delete file: %s", doc.storage_path) + logger.warning("Could not delete file: %s", doc.storage_path, exc_info=True) return await document_repo.delete(doc_id) @@ -101,6 +105,9 @@ def _count_pages(file_content: bytes) -> int | None: try: info = pdfinfo_from_bytes(file_content) return info.get("Pages") - except Exception: - logger.warning("Could not count pages", exc_info=True) + except (FileNotFoundError, OSError) as exc: + logger.warning("Could not count pages: %s", exc) + return None + except Exception: + logger.warning("Unexpected error counting pages", exc_info=True) return None