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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions