Skip to content

Skip a malformed app record instead of 500ing the app search page#8933

Merged
kodjima33 merged 2 commits into
BasedHardware:mainfrom
ZachL111:zach/apps-search-poison-guard
Jul 4, 2026
Merged

Skip a malformed app record instead of 500ing the app search page#8933
kodjima33 merged 2 commits into
BasedHardware:mainfrom
ZachL111:zach/apps-search-poison-guard

Conversation

@ZachL111

@ZachL111 ZachL111 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

What

GET /v2/apps/search (search_apps) builds App(**app_dict) in a loop over raw Firestore app documents with no per-record guard. App has required no-default fields (id, name, category, author, description, image, capabilities), so one legacy or malformed app document raised pydantic.ValidationError and 500'd the entire search result for the user.

Change

Wrap the per-record build in try/except ValidationError: skip the malformed record and log its id plus the offending field names (never the field values). This matches the recently merged marketplace-listing guard and the other per-record ValidationError guards already in this router. Single-file change in backend/routers/apps.py.

Test

New backend/tests/unit/test_apps_search_poison_guard.py: a search returning one valid app and one malformed record (missing required fields) returns the valid app and skips the bad one instead of 500ing. Imports the router normally, patches the db helpers with monkeypatch.setattr, and calls the handler directly.

Review in cubic

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 2 files

Confidence score: 3/5

  • In backend/routers/apps.py, direct app['id']/app_dict['id'] access in both the pre-loop comprehension and the loop can still raise on malformed records, so the search page may return a 500 despite the new ValidationError handling; broaden the guard to cover all id reads (or use safe access/skip invalid records) and add a regression test for missing-id entries before merging.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread backend/routers/apps.py

@Git-on-my-level Git-on-my-level left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice robustness fix — thanks @ZachL111. One malformed Firestore app document 500'ing the entire /v2/apps/search page for users is a real bug, and the guard matches the existing per-record ValidationError pattern already used by the marketplace listing endpoints (_safe_build_app) and elsewhere in this router. Logging the id + offending field locs (never values) is the right call.

Test looks good — covers the skip-and-continue path with a valid + malformed record pair, and follows the established unit-test conventions (os.environ.setdefault, monkeypatch the db helpers, call the handler directly).

Approving. One small optional nit for later: the marketplace listing loops in this file already route through _safe_build_app in utils/apps.py; if search_apps ever wants to centralize too, it could reuse that helper instead of an inline try/except. Not blocking.

ZachL111 added 2 commits July 4, 2026 04:28
GET /v2/apps/search (search_apps) builds App(**app_dict) in a loop over raw app
documents with no per-record guard, so one legacy or malformed app document raised
ValidationError and 500'd the entire search result. Skip and log the bad record
instead, matching the marketplace-listing guard and the other per-record guards in this
router. Adds a unit test that a malformed record is dropped while the valid app still
comes through.
cubic flagged that the ValidationError guard was too narrow: a record missing id would KeyError
in the app_ids list and the installs/reviews/enabled lookups before the guard ever runs, still
500ing the search page. Drop id-less records up front (logging the count) so the page survives.
@ZachL111 ZachL111 force-pushed the zach/apps-search-poison-guard branch from ee24589 to d488623 Compare July 4, 2026 11:28

@kodjima33 kodjima33 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Backend bug fix with test + green CI: per-record ValidationError guard prevents one malformed record from 500ing the endpoint (conf 5/5).

@kodjima33 kodjima33 merged commit 3688589 into BasedHardware:main Jul 4, 2026
4 checks passed
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.

3 participants