Skip to content

[GIT-213] fix: return HTTP response from dispatch() exception handler#9179

Merged
sriramveeraghanta merged 2 commits into
previewfrom
fix/git-213-dispatch-returns-response
Jun 1, 2026
Merged

[GIT-213] fix: return HTTP response from dispatch() exception handler#9179
sriramveeraghanta merged 2 commits into
previewfrom
fix/git-213-dispatch-returns-response

Conversation

@sriramveeraghanta
Copy link
Copy Markdown
Member

@sriramveeraghanta sriramveeraghanta commented May 30, 2026

Description

When an API request triggered an unhandled exception, the shared view bases caught it, built the proper error Response via handle_exception(), but then returned the raw exception object instead of the response:

except Exception as exc:
    response = self.handle_exception(exc)
    return exc          # ← should be `return response`

Django's response pipeline then failed with TypeError: 'Exception' object is not a valid HTTP response, so clients received a malformed 500 with no structured body instead of a clean JSON error.

The same copy-pasted defect existed in six dispatch() methods across four files, so this PR fixes all of them — not only the one reported in the issue — so the crash cannot surface from the external API, app, space, or license surfaces:

  • apps/api/plane/api/views/base.pyBaseAPIView
  • apps/api/plane/app/views/base.pyBaseViewSet, BaseAPIView
  • apps/api/plane/license/api/views/base.pyBaseAPIView
  • apps/api/plane/space/views/base.pyBaseViewSet, BaseAPIView

(api.BaseViewSet already returned response correctly, which confirmed the intended fix.)

A parametrized regression test covers every affected base class and asserts that, when super().dispatch() raises, dispatch() returns an HTTP Response rather than the exception.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Feature (non-breaking change which adds functionality)
  • Improvement (change that would cause existing functionality to not work as expected)
  • Code refactoring
  • Performance improvements
  • Documentation update

Screenshots and Media (if applicable)

Test Scenarios

  • Added apps/api/plane/tests/unit/views/test_base_dispatch.py: parametrized over all six affected base classes plus api.BaseViewSet as a control; asserts dispatch() returns a rest_framework.response.Response (not the exception) when super().dispatch() raises. Verified RED (6 failures) before the fix and GREEN (7 passing) after.
  • Full API suite via docker compose -f docker-compose-test.yml up --build --abort-on-container-exit --exit-code-from api-tests: 236 passed (exit code 0), including DB-backed contract/model/serializer tests.
  • ruff check passes on all changed files.
  • Manual: trigger any API endpoint that raises an unhandled exception and confirm the client receives a structured {"error": ...} JSON body with a 500 status instead of a crashed response pipeline.

References

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed exception handling in API request dispatching so callers receive consistent, formatted error responses (HTTP payloads/statuses) instead of raw exception objects.
  • Tests

    • Added regression tests to verify exception handling behavior across multiple API view implementations.
  • Chores

    • Added license header to a test package file.

BaseAPIView.dispatch() and BaseViewSet.dispatch() built the proper
error Response via handle_exception() but returned the raw exception
object instead, causing Django to raise
"TypeError: 'Exception' object is not a valid HTTP response".

Fix all six occurrences across the api, app, license and space view
bases, and add a regression test covering every affected base class.

Fixes #9157
Copilot AI review requested due to automatic review settings May 30, 2026 18:22
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 30, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0a7b2902-94da-4c18-844d-9fab38ae4ff0

📥 Commits

Reviewing files that changed from the base of the PR and between 97f5e4f and 379d42f.

📒 Files selected for processing (1)
  • apps/api/plane/tests/unit/views/__init__.py

📝 Walkthrough

Walkthrough

Fixes dispatch() return paths in Plane API base views so exception handlers return the DRF Response from handle_exception(exc) and success paths return the computed response; adds a regression test asserting this behavior.

Changes

Dispatch Exception Handling Correction

Layer / File(s) Summary
Core dispatch exception and success-path returns
apps/api/plane/api/views/base.py, apps/api/plane/app/views/base.py, apps/api/plane/license/api/views/base.py, apps/api/plane/space/views/base.py
All four base view modules now return the Response produced by handle_exception(exc) in exception paths and return the computed response on success paths.
Regression test and header
apps/api/plane/tests/unit/views/test_base_dispatch.py, apps/api/plane/tests/unit/views/__init__.py
Adds a parametrized unit test that mocks super().dispatch() to raise and asserts dispatch() calls handle_exception() once and returns its Response; also adds file header comments.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related issues

  • #8932: Identical bug fix touching the same dispatch() implementations; both replace erroneous return exc with return response.

🐰 I hopped through traces and logs so deep,
Fixed dispatch so errors no longer leap,
Now responses return in proper form,
No raw exceptions to break the storm,
A tiny hop — the API sleeps sweet.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main fix: returning the HTTP response instead of the exception object from dispatch() exception handlers.
Description check ✅ Passed The description comprehensively covers the bug, affected files, solution approach, test coverage, and verification steps following the repository's template structure.
Linked Issues check ✅ Passed The PR fully addresses issue #9157 by fixing all six affected dispatch() methods to return the HTTP Response instead of the exception object, including comprehensive regression testing.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the dispatch() exception handling bug across all affected base classes and include only necessary regression test coverage.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/git-213-dispatch-returns-response

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@makeplane
Copy link
Copy Markdown

makeplane Bot commented May 30, 2026

Linked to Plane Work Item(s)

This comment was auto-generated by Plane

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a copy-pasted bug in six dispatch() methods across four base view modules where the raw exception was returned instead of the HTTP Response produced by handle_exception(), causing Django's response pipeline to fail with TypeError: 'Exception' object is not a valid HTTP response.

Changes:

  • Replace return exc with return response in the exception handler of dispatch() for BaseAPIView/BaseViewSet across api, app, license, and space view bases.
  • Add a parametrized regression unit test covering all affected base classes plus the already-correct api.BaseViewSet as a control.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
apps/api/plane/api/views/base.py Return Response from BaseAPIView.dispatch() exception path.
apps/api/plane/app/views/base.py Return Response from BaseViewSet/BaseAPIView dispatch() exception paths.
apps/api/plane/license/api/views/base.py Return Response from BaseAPIView.dispatch() exception path.
apps/api/plane/space/views/base.py Return Response from BaseViewSet/BaseAPIView dispatch() exception paths.
apps/api/plane/tests/unit/views/test_base_dispatch.py Parametrized regression test asserting dispatch() returns the Response, not the exception.
apps/api/plane/tests/unit/views/init.py New empty package init for the test directory.

The empty package init file was missing the AGPL copyright header,
failing the Copy Right Check CI (addlicense -check on all tracked
.py files).
@sriramveeraghanta sriramveeraghanta merged commit 011328c into preview Jun 1, 2026
10 of 11 checks passed
@sriramveeraghanta sriramveeraghanta deleted the fix/git-213-dispatch-returns-response branch June 1, 2026 09:33
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.

dispatch() Returns Exception Object Instead of HTTP Response in BaseAPIView

3 participants