Skip to content

Answer unknown /api URLs with a JSON 404 - #2618

Open
SajalDevX wants to merge 3 commits into
FlexMeasures:mainfrom
SajalDevX:fix/json-404-under-api
Open

SajalDevX wants to merge 3 commits into
FlexMeasures:mainfrom
SajalDevX:fix/json-404-under-api

Conversation

@SajalDevX

@SajalDevX SajalDevX commented Sep 29, 2026 •

Copy link
Copy Markdown

Description

Closes #2598

error_handling_router decided between a JSON and an HTML response by looking at request.url_rule, which is None when no route matched, so an unknown URL under /api (a typo, an outdated API version) got the HTML error page unless the request carried a JSON content type. It now checks request.path.startswith("/api"), as proposed in the issue, so every error under /api is answered in JSON.

Request Before After
GET /api/v3_0/no-such-endpoint (no content type) 404, text/html 404, application/json
GET /api/v3_0/no-such-endpoint with Content-Type: application/json 404, application/json unchanged
GET /no-such-page (no content type) HTML 404 unchanged

How to test

pytest flexmeasures/utils/tests/test_error_utils.py — new tests on a bare Flask app with only add_basic_error_handlers (plus a dummy HTML handler to tell the two apart): three unknown /api paths get a JSON 404 with message and status; an unknown non-API path still gets HTML; a JSON request outside /api still gets JSON. The three /api cases fail on main. I don't have a Postgres at hand, so the full app tests I could not run here.

Further Improvements

None.

Related Items

Change-log entries added under v3.0-40 in documentation/api/change_log.rst and under Bugfixes in documentation/changelog.rst.


  • I agree to contribute to the project under Apache 2 License.
  • To the best of my knowledge, the proposed patch is not based on code under GPL or other license that is incompatible with FlexMeasures
  • I have read and understood the CONTRIBUTING.md in this repo
  • Have added a changelog entry

error_handling_router decided between JSON and HTML by looking at the
matched URL rule, which is None when no route matched, so an unknown URL
under /api fell through to the HTML error page unless the request itself
carried a JSON content type. Decide on the request path instead, so every
error under /api is answered in JSON.

Adds tests on a bare Flask app with only the generic error handler, and
entries in the API change log and the changelog.

Closes FlexMeasures#2598
@read-the-docs-community

read-the-docs-community Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

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.

Copilot review overview

🟡 Changes recommended

The new test’s HTML fallback handler is misnamed (NotFoundError_handler_html vs NotFound_handler_html), which will prevent the intended HTML-vs-JSON distinction from working as asserted.

Review effort: Lite
Findings: 1 High severity · 1 Low severity

Open (2)
What changed in this PR

This PR fixes error response negotiation so that unknown URLs under /api consistently return a JSON 404 (instead of the HTML error page when no route matches), aligning behavior for API clients and addressing #2598.

Changes:

  • Update error_handling_router to decide JSON vs HTML based on request.path.startswith("/api") rather than request.url_rule.
  • Add focused tests using a bare Flask app to ensure unknown /api paths return JSON 404, while non-API paths keep HTML behavior.
  • Add changelog entries documenting the behavior change for both general users and API consumers.
File Description
flexmeasures/​utils/​error_utils.py Routes all errors under /api to JSON responses even when no Flask route matched
flexmeasures/​utils/​tests/​test_error_utils.py Adds regression tests for unknown /api URLs and preserves HTML behavior outside /api
documentation/​changelog.rst Notes the bugfix in the main changelog under Bugfixes
documentation/​api/​change_log.rst Documents the API-facing behavior change under v3.0-40

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +12 to +16
app.NotFoundError_handler_html = lambda error: (
"<html>not found</html>",
404,
{"Content-Type": "text/html"},
)
Comment on lines +65 to 67
We respond in JSON if the request content-type is JSON, if the request was made under /api
(whether or not it matched a route, so that an unknown API URL gets a JSON 404, too),
or if the error is a SecurityError.
Signed-off-by: Nicolas Höning <nicolas@seita.nl>

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unknown /api URLs get an HTML 404 page instead of JSON

3 participants