Skip to content

/us/calculate-full returns 500 (should be 400) for malformed axis input from crawler traffic #3740

Description

@anth-volk

Summary

/us/calculate-full returns HTTP 500 for malformed request bodies where it should return 400 (client error). The engine raises SituationParsingError on bad input, but the endpoint surfaces it as a server error, which inflates the 5xx rate and any 5xx-based alerting.

Observed

A steady stream (~8 in 15 min, ~28/hr, ~230 over 6h) of:

File "policyengine_api/endpoints/household.py", line 276, in get_calculate
    result = country.calculate(household_json, policy_json)
...
policyengine_core.errors.SituationParsingError:
  {'people': {'you': {'employment_income':
     [None, None, … (~300 entries) …, "Can't deal with value: expected type number, received '{}'."]}}}

The request body contains an employment_income axis where one value is an empty object {} instead of a number. The request fails immediately (<1 ms), before any compute.

Source

Unauthenticated crawler traffic — Facebook's facebookexternalhit/1.1 link-preview bot plus node clients from Meta IP ranges (2a03:2880::/32, 57.128.0.0/10) re-crawling shared policyengine.org links whose encoded household carries the malformed axis value. No API key or user is attached. Migration telemetry on these requests: route_impl: flask_fallback, sim_compute: old_gateway, api_host_backend: app_engine.

Impact

  • No user-facing harm (bot traffic on old shared links), but it pollutes the 5xx error rate / alerting and inflates log volume.
  • Exposes that a shareable-link generator can emit an axis value of {}.

Possible fixes

  1. Map SituationParsingError (and malformed-input parsing failures generally) to HTTP 400 with a clear error body, instead of 500.
  2. Validate/reject non-numeric axis values (e.g. {}) at the input boundary with a 400.
  3. Trace which shared-URL pattern encodes the {} so the link generator can be corrected.

Priority: low. Filed for tracking — not scheduled for immediate work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions