Skip to content

SQ-925: Refactor DivBase API's exception handling #107

Merged
RMCrean merged 2 commits into
mainfrom
api-exception-handling
Jul 3, 2026
Merged

SQ-925: Refactor DivBase API's exception handling #107
RMCrean merged 2 commits into
mainfrom
api-exception-handling

Conversation

@RMCrean

@RMCrean RMCrean commented Jul 3, 2026

Copy link
Copy Markdown
Member

This PR refactors the current exceptions.py and exception_handlers.py approach used for DivBase API. The prior strategy was ready for some cleanup as each exception_handler fn was repeating essentially the exact same steps. Now that we have quite a lot of exceptions, it makes sense to reduce some of this duplication.

New approach:

  • Every DivBaseAPIException subclass uses class attributes to define how it should be handled by a generic exception handler function (divbase_api_exception_handler).
  • This works for almost all exceptions but a few still have custom exception handling in exception_handlers.py. For example UserRegistrationError (error can be raised by admin or signing up user) or RequestValidationError - pydantic error which contains a list of 1 or more exceptions. This works fine because fastapi uses the exception handler that is most specific to the exception.

Other changes

  1. Use exception __name__ as the exception "type" in the API response, rather than a camel case form of the name
  2. Set more appropriate logging levels (and whether to include traceback in logs) for diff exception types.
  3. Delete unused exceptions and reorder exception classes to group them by category.
  4. Tests updated to handle swap to PascalCase for error types reported by the API.
  5. Fix a bug that frontend 404 errors were not displaying the custom error page.

RMCrean added 2 commits July 3, 2026 12:01
1. Use class attributes on DivBaseAPIException subclasses to define how each exception should be handled
and then have a generic exception handler that uses those attributes to determine the response. Rather than 1 handler per exception.

2. Use exception __name__ as the exception "type" in the API response, rather than a camel case form of the name

3. Set more appropriate logging levels for diff exception types.

4. Delete unused exceptions and reorder exception classes to group them by category.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors DivBase API exception handling by consolidating most custom exception handlers into a single generic handler driven by per-exception class attributes, while updating CLI/E2E tests and frontend error rendering to match the new error “type” format (__name__).

Changes:

  • Introduces a generic divbase_api_exception_handler for DivBaseAPIException subclasses and streamlines handler registration.
  • Updates E2E CLI tests to expect PascalCase exception types (class __name__) in error outputs/responses.
  • Improves frontend 404 rendering by allowing a specific error message to be displayed on the 404 template.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/e2e_integration/cli_commands/test_version_cli.py Updates expected API error type strings to match exception class names.
tests/e2e_integration/cli_commands/test_task_history_cli.py Updates expected authorization/project-not-found error identifiers to PascalCase.
tests/e2e_integration/cli_commands/test_queue_status.py Updates expected queue-closed error identifiers to PascalCase.
tests/e2e_integration/cli_commands/test_personal_access_tokens.py Updates expected auth/authz error identifiers to PascalCase.
tests/e2e_integration/cli_commands/test_middleware.py Updates expected CLI-version error type to CLIVersionOutdatedError.
tests/e2e_integration/cli_commands/test_dimensions_cli.py Updates expected dimensions-related error identifiers to PascalCase.
tests/e2e_integration/cli_commands/test_auth_cli.py Updates expected CLI-version error identifiers to PascalCase.
packages/divbase-api/src/divbase_api/templates/404.html Allows optional error_message to be shown on the 404 page (fallbacks to default text).
packages/divbase-api/src/divbase_api/middleware.py Aligns CLI-version rejection response type and uses status.HTTP_400_BAD_REQUEST.
packages/divbase-api/src/divbase_api/exceptions.py Adds per-exception handling metadata (log level, traceback inclusion, frontend behavior) and standardizes error_type.
packages/divbase-api/src/divbase_api/exception_handlers.py Replaces many specific handlers with a single generic handler + a few special cases; adjusts logging and response type values.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if is_api_request(request):
if _is_api_request(request):
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://fastapi.tiangolo.com/reference/status/#fastapi.status.HTTP_422_UNPROCESSABLE_CONTENT

HTTP_422_UNPROCESSABLE_CONTENT is correct, comment is outdated advice.

return await _render_error_page(
request=request,
message=f"Badly formatted request. Please check your input and try again. Details: {errors}",
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://fastapi.tiangolo.com/reference/status/#fastapi.status.HTTP_422_UNPROCESSABLE_CONTENT

HTTP_422_UNPROCESSABLE_CONTENT is correct, comment is outdated advice.

Comment on lines 112 to +114
class ProjectCreationError(DivBaseAPIException):
def __init__(self, message: str = "Project creation failed"):
super().__init__(message=message, status_code=status.HTTP_400_BAD_REQUEST)

log_level = logging.WARNING
include_exc_info = True

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no frontend route that can raise this (as Project Creation is only done by admin panel or API), so was just dead code.

Comment on lines +227 to +229
log_level = logging.INFO
include_exc_info = False

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error does not get raised by the frontend so it was dead code, I see the worker (which user could potentially see because we give user logs for vcf queries), catches and re-raises with a custom error, so safe to ignore this comment.

@RMCrean RMCrean marked this pull request as ready for review July 3, 2026 10:42
@RMCrean RMCrean requested a review from a team as a code owner July 3, 2026 10:42
@RMCrean RMCrean merged commit d3b3267 into main Jul 3, 2026
4 checks passed
@RMCrean RMCrean deleted the api-exception-handling branch July 3, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants