Skip to content

Silently drops MONTH-defined variable inputs keyed annually #1489

@hua7450

Description

@hua7450

Summary

When the v2 household API receives an input for a definition_period = MONTH variable keyed to an annual period (e.g., {"2026": ...} instead of {"2026-01": ...}), the value is silently discarded and the variable falls back to its default. The API still returns status: ok with a plausible-looking benefit number, giving partners no signal that their request was malformed.

This contrasts with v1 (api.policyengine.org), which broadcasts the annual value into every month. Whether v1's behavior is "right" is debatable, but at least it surfaces obviously wrong inputs (extreme income → $0 benefit), whereas v2 produces silently wrong outputs (income ignored → max benefit).

Reproductions

Numeric MONTH variable — snap_earned_income

Single 34-year-old, WA, payload sets snap_earned_income: {"2026": 31932} (and equivalent housing_cost).

  • v1: broadcasts $31,932/month → way over limit → snap: $0 (the input was used, even if wildly).
  • v2: drops the value, falls back to $0 → looks fully eligible → snap: $298 (1-person FY2026 max allotment).

Enum MONTH variable — de_ssp_living_arrangement

Aged 70, DE, payload sets de_ssp_living_arrangement: {"2026": "CERTIFIED_RESIDENTIAL_CARE_HOME"}.

  • v1 (with version-correct enum name RESIDENTIAL_CARE): broadcasts → de_ssp: $140, eligible.
  • v2: drops the value, falls back to default_value = NONEde_ssp: $0, ineligible.

If the same payload is rekeyed monthly ({"2026-01": ...}), both APIs agree.

Why this is the worst-of-three behavior

  • Hard reject (preferred): client gets a 400 telling them the period key is wrong; bug never reaches production.
  • Broadcast (v1's choice): visibly wrong outputs reveal the bad input quickly during development.
  • Silent drop (v2's current behavior): the response looks correct. Partners integrating against v2 have no way to know their request was malformed unless they cross-check externally — which is how this was discovered.

Proposed resolution

Either:

  1. Reject the request with a 400 and a message like period key '2026' is invalid for variable 'snap_earned_income' (definition_period = MONTH); use 'YYYY-MM'.
  2. Broadcast the annual value to every month (matching v1), so at least the input is used.

Pick one and document it on the /us/api docs page. Either is strictly better than today's silent-default behavior.

Optional: validate request period keys against each variable's definition_period at request-parse time, so the error fires before any calculation runs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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