Skip to content

fix(api): return 422 for out-of-range pagination query values - #15223

Open
Lesereingrape wants to merge 1 commit into
langflow-ai:mainfrom
Lesereingrape:fix/pagination-query-bounds
Open

Lesereingrape wants to merge 1 commit into
langflow-ai:mainfrom
Lesereingrape:fix/pagination-query-bounds

Conversation

@Lesereingrape

@Lesereingrape Lesereingrape commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

Changes

custom_params declared page/size as unbounded Query(None) and then passed them to fastapi_pagination.Params, which validates size as ge=1, le=100 itself. So an out-of-range value raised ValidationError during dependency resolution — before the handler, which puts it past the route's own try/except and into the app-wide Exception handler in main.py, answering 500 with the internal validation text echoed to the client.

This declares the same bounds on the query parameters so FastAPI rejects them as 422, matching the sibling routes that already depend on Params directly.

Fixes #15222

Affected routes: /api/v1/monitor/transactions, /api/v1/projects/{project_id}, /api/v1/folders/{folder_id}.

Nothing that works today changes: None for both parameters still means "unpaginated", size=100 is still the ceiling, and ?page=3 still defaults size to MAX_PAGE_SIZE. page=0 / size=0 now return 422 instead of being silently rewritten to the defaults.

How was this tested

src/backend/tests/unit/api/test_api_utils.py — a minimal FastAPI() app whose only dependency is custom_params, so no database, no network, no service setup:

  • 5 out-of-range cases assert 422 (3 that used to be 500, 2 that used to be a silently rewritten 200)
  • 5 accepted cases assert the same 200 payloads as before, including "no query parameters at all"
  • 1 drift guard pins MAX_PARAMS_PAGE_SIZE/MIN_PAGE_SIZE against the bounds Params itself carries, because the bounds are now declared in two places

Measured locally on main @ 5621dcfd (Python 3.12, uv, Windows):

# new tests, original unbounded declarations kept:  5 failed, 6 passed
#   assert 500 == 422  (size=101, size=1000, size=-5)
#   assert 200 == 422  (size=0, page=0)
# new tests, with this commit:                     11 passed
# whole module (uv run pytest src/backend/tests/unit/api/test_api_utils.py): 28 passed
# uv run ruff format --diff <both files> -> 2 files already formatted
# uv run ruff check <both files>         -> All checks passed!

make format_backend / make unit_tests were not run — make is not available on this machine, so the uv run equivalents above are what actually executed. Importing and building the monitor, projects and folders routers was also checked, because FastAPI validates a Query bound at route-build time: all three still build (this is what caught an earlier version of the fix that put the None default inside Annotated, which FastAPI rejects).

What else to consider

  • The 500 also leaked the raw validation string. It is not sensitive in this case, but if the team wants a consistent error envelope, the app-wide handler could stop echoing str(exc) — out of scope here.
  • MAX_PAGE_SIZE = 50 is still only a default, not a bound, so the accepted ceiling stays 100 (what Params allows). Tightening it to 50 would turn currently-working size=51..100 requests into 422s, so I deliberately left it alone.
  • MIN_PAGE_SIZE is reused as the ge for both parameters; it already equals the ge=1 that Params puts on page.

Attribution: this change was prepared by an AI coding agent working from the account holder's instruction, and has not been reviewed by a human before opening. The RED/GREEN numbers above are measured output, not estimates.

Summary by CodeRabbit

  • Bug Fixes
    • Invalid pagination values are now rejected with a clear HTTP 422 response instead of causing a server error.
    • Pagination parameters enforce valid minimum values, with page sizes capped at 100.
    • Valid pagination values continue to be accepted and processed as expected.

custom_params declared page/size as unbounded Query(None) and then handed
them to fastapi_pagination.Params, whose own constraints validate size as
ge=1, le=100. An out-of-range value therefore raised ValidationError inside
dependency resolution: the route never ran and the app-wide Exception handler
answered 500 with the raw validation text, while falsy values (page=0,
size=0) were silently rewritten to defaults.

Declare the same bounds on the query parameters so FastAPI rejects them as
422, matching what the sibling routes built on Depends(Params) already do.
@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: langflow-ai/langflow/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 5fb86466-fdeb-40d7-a721-9489eacabdc9

📥 Commits

Reviewing files that changed from the base of the PR and between 5621dcf and 65e5349.

📒 Files selected for processing (2)
  • src/backend/base/langflow/api/utils/core.py
  • src/backend/tests/unit/api/test_api_utils.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


Walkthrough

The shared custom_params dependency now validates pagination bounds through FastAPI. Invalid values return HTTP 422 before Params construction. Tests cover invalid values, accepted values, and alignment with fastapi-pagination constraints.

Changes

Pagination validation

Layer / File(s) Summary
Custom pagination query bounds
src/backend/base/langflow/api/utils/core.py
Adds MAX_PARAMS_PAGE_SIZE and applies FastAPI bounds to page and size in custom_params.
Pagination validation coverage
src/backend/tests/unit/api/test_api_utils.py
Adds an isolated FastAPI client and tests for HTTP 422 responses, accepted values, and matching Params bounds.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: erichare

🚥 Pre-merge checks | ✅ 8 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (8 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: returning HTTP 422 for out-of-range pagination query values.
Linked Issues check ✅ Passed The change addresses issue #15222. custom_params now declares page >= 1 and 1 <= size <= 100 with FastAPI Query bounds. FastAPI therefore rejects invalid values with HTTP 422 before Params c…
Out of Scope Changes check ✅ Passed The reviewed changes are limited to pagination validation in core.py and supporting unit tests in test_api_utils.py. The new constant and tests directly support issue #15222. No unrelated product …
Test Coverage For New Implementations ✅ Passed The PR includes regression coverage in the project-named backend test file src/backend/tests/unit/api/test_api_utils.py. The new FastAPI TestClient tests exercise custom_params through dependenc…
Test Quality And Coverage ✅ Passed The added pytest coverage is focused and behavior-based. A FastAPI test route uses the same Annotated[Params | None, Depends(custom_params)] dependency as the affected routes. Five invalid cases a…
Test File Naming And Structure ✅ Passed PASS. The changed backend test file is named test_api_utils.py and is under src/backend/tests/unit/api, which matches the repository pytest layout. It uses pytest fixtures and parametrization with…
Excessive Mock Usage Warning ✅ Passed No excessive mock usage was introduced. The changed pagination tests use real FastAPI, TestClient, Depends, custom_params, and Params objects, so they exercise dependency validation and resp…
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

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 bug Something isn't working and removed bug Something isn't working labels Sep 20, 2026

This branch has not been deployed

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Out-of-range page/size on transactions/projects/folders returns 500 instead of 422

1 participant