Skip to content

feat: better communicate limits in Core API errors - #8206

Closed
srijantrpth wants to merge 5 commits into
Flagsmith:mainfrom
srijantrpth:8130-standardize-api-limit-errors
Closed

feat: better communicate limits in Core API errors#8206
srijantrpth wants to merge 5 commits into
Flagsmith:mainfrom
srijantrpth:8130-standardize-api-limit-errors

Conversation

@srijantrpth

Copy link
Copy Markdown
Contributor

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Closes #8130

Standardized Core API errors to better communicate limits and gates to API clients:

  • Paywall/Plan Gates (e.g., organization seat limits): Configured to return 402 Payment Required, contain "code": "invalid-plan", and direct users to https://www.flagsmith.com/pricing in the human-readable description.
  • System Limits (e.g., project entity size limits): Configured to return 400 Bad Request, contain "code": "system-limit", and direct users to https://docs.flagsmith.com/support#getting-in-touch in the human-readable description.

How did you test this code?

  • Updated unit tests in tests/unit/organisations/invites/test_unit_invites_views.py to assert 402 Payment Required, the "invalid-plan" code, and the new pricing detail strings for seat limit violations.
  • Updated unit tests in tests/unit/projects/test_unit_projects_views.py to assert 400 Bad Request, the "system-limit" code, and the updated support detail strings for project size limit violations.
  • Ran the backend test suite locally via pytest to ensure 100% passing tests for both updated domains.

- Introduced specific `402 Payment Required` exceptions for paywall and plan limits (replacing generic 400 Bad Request errors).
- Updated organization invite views to return 402 when seat limits are exceeded.
- Updated project edge migration views to return 402 when project size limits (identities, features, segments) are exceeded.
- Standardized error detail messages to include direct links to pricing and support documentation.
- Updated all related unit tests in `test_unit_invites_views.py` and `test_unit_projects_views.py` to assert the new 402 status codes and updated detail strings.
Copilot AI review requested due to automatic review settings August 2, 2026 14:49
@srijantrpth
srijantrpth requested a review from a team as a code owner August 2, 2026 14:49
@srijantrpth
srijantrpth requested review from emyller and removed request for a team August 2, 2026 14:49
@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown

@srijantrpth is attempting to deploy a commit to the Flagsmith Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e1af99d2-622f-4591-bfb6-fcd55d1ba1bb

📥 Commits

Reviewing files that changed from the base of the PR and between 6ad876a and b70935c.

📒 Files selected for processing (5)
  • api/app/exceptions.py
  • api/app/settings/common.py
  • api/projects/exceptions.py
  • api/tests/unit/organisations/invites/test_unit_invites_views.py
  • api/tests/unit/projects/test_unit_projects_views.py

📝 Walkthrough

Walkthrough

Organisation and subscription plan errors now return HTTP 402 with the invalid-plan code and pricing guidance. Project limit errors now share a SystemLimitError base with HTTP 400, the system-limit code, and support guidance. A custom exception handler adds string error codes to API responses. Unit tests assert the updated responses.

Estimated code review effort: 3 (Moderate) | ~20 minutes

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

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.

@github-actions github-actions Bot added the api Issue related to the REST API label Aug 2, 2026

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

This PR standardises Core API error responses for plan-gated limits vs adjustable system limits, aiming to provide clearer guidance (pricing vs support) to API clients and end users.

Changes:

  • Updated subscription / organisation exceptions to use 402 Payment Required for plan-gated limits and include pricing guidance in the human-readable detail.
  • Introduced a SystemLimitError base exception for project “size / count” limits with updated support guidance, and updated related unit tests to assert the new detail strings.
  • Refreshed unit tests for invite-seat limit and project migration limit scenarios to match the new status codes / messages.

Reviewed changes

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

Show a summary per file
File Description
api/tests/unit/projects/test_unit_projects_views.py Updates assertions for “system limit” project migration failures to use the new support-directed detail strings.
api/tests/unit/organisations/invites/test_unit_invites_views.py Updates assertions for seat-limit failures to return 402 and include the pricing URL in the detail message.
api/projects/exceptions.py Adds a SystemLimitError base class and updates project limit exceptions to inherit it / use support-directed messaging.
api/organisations/subscriptions/exceptions.py Introduces a base “invalid plan” exception with 402 + invalid-plan default code and pricing-directed detail; uses it for seat upgrade gating.
api/organisations/exceptions.py Updates “no paid subscription” to be treated as an “invalid plan” style error (402 + pricing-directed detail).
Suppressed comments (4)

api/tests/unit/organisations/invites/test_unit_invites_views.py:144

  • This test now asserts 402 Payment Required, but the test name still says "returns_400". Renaming the test keeps the test intent accurate and makes failures easier to interpret.
    assert response.status_code == status.HTTP_402_PAYMENT_REQUIRED

api/tests/unit/organisations/invites/test_unit_invites_views.py:298

  • This test now asserts 402 Payment Required, but the test name still says "returns_400". Renaming the test keeps the test intent accurate and makes failures easier to interpret.
    assert response.status_code == status.HTTP_402_PAYMENT_REQUIRED

api/tests/unit/organisations/invites/test_unit_invites_views.py:371

  • This test now asserts 402 Payment Required, but the test name still says "returns_400". Renaming the test keeps the test intent accurate and makes failures easier to interpret.
    assert response.status_code == status.HTTP_402_PAYMENT_REQUIRED

api/tests/unit/organisations/invites/test_unit_invites_views.py:403

  • This test now asserts 402 Payment Required, but the test name still says "returns_400". Renaming the test keeps the test intent accurate and makes failures easier to interpret.
    assert response.status_code == status.HTTP_402_PAYMENT_REQUIRED

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

Comment thread api/organisations/subscriptions/exceptions.py
Comment thread api/tests/unit/organisations/invites/test_unit_invites_views.py
Comment thread api/projects/exceptions.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 14b4a46e-15ae-4213-80a4-11314de6ccc1

📥 Commits

Reviewing files that changed from the base of the PR and between fc33002 and 6ad876a.

📒 Files selected for processing (5)
  • api/organisations/exceptions.py
  • api/organisations/subscriptions/exceptions.py
  • api/projects/exceptions.py
  • api/tests/unit/organisations/invites/test_unit_invites_views.py
  • api/tests/unit/projects/test_unit_projects_views.py

Comment thread api/organisations/subscriptions/exceptions.py
Comment thread api/projects/exceptions.py Outdated
Comment thread api/tests/unit/organisations/invites/test_unit_invites_views.py
Comment thread api/tests/unit/projects/test_unit_projects_views.py
srijantrpth and others added 2 commits August 2, 2026 15:13
- Added a custom DRF exception handler in `api/app/exceptions.py` to ensure `default_code` is exposed in the JSON response payload.
- Removed duplicated imports and duplicated exception class definitions in `api/projects/exceptions.py`.
- Renamed invite tests in `test_unit_invites_views.py` to accurately reflect the new `402` status code.
- Added assertions for `"code": "invalid-plan"` and `"code": "system-limit"` across invite and project unit tests to verify the new handler works as expected.
@matthewelwell

Copy link
Copy Markdown
Contributor

Hi @srijantrpth, thanks for the contribution. I'm sorry, but we do not accept PRs for issues that relate to payments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Issue related to the REST API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Better communicate our limits in Core API errors

3 participants