← All use cases Backend incident

A 500 on the portfolio endpoint

PRODE-286invest-apiSeverity P2Caught by synthetic monitor

Trigger

The Cur8Api5XXAlarm (eu-west-2) fired at 05:18 UTC, set off by the Checkly synthetic monitor probing GET /commitments-v2. The probe caught it first, but any investor whose commitment list landed in the same shape would have hit the same 500 on their portfolio.

What the agent saw

One 500 in CloudWatch (Cur8ApiLogGroup), captured to Sentry, with a clean stack:

TypeError: Cannot destructure property 'investments' of
'transactionResources' as it is undefined.
  at CommitmentCoreService.shouldShowCommitmentOnPortfolio
  at CommitmentCoreService.getInvestorCommitments
  at CommitmentControllerV2.getInvestorCommitments

Investigation

getInvestorCommitments builds a map of transaction resources keyed by commitment id, then iterates the commitment list. shouldShowCommitmentOnPortfolio destructures that resources object with no guard — so any commitment present in the list but missing from the map throws.

Not a regression: the destructure was authored in Dec 2024, the unguarded call site in Feb 2025. It sat latent for months; the synthetic probe simply hit a triggering shape. A commitment can be missing from the map when the resources query returns fewer rows than requested (a race against deletion, an eager-load edge case, or an id-coercion mismatch between the queries).

The fix · #9591

Default to an empty transaction-resources object at the call site (and the sibling call sites). That is semantically identical to a commitment with no transactions, so the endpoint returns the correct result instead of throwing.

Verification & outcome

The 500 is eliminated; the endpoint now falls back to the correct "no transactions → don't show on portfolio" behaviour. A follow-up was logged to chase the underlying map inconsistency, so the surgical fix doesn't mask it forever.

Knowledge-graph node

Error "Cannot destructure investments" → caused by commitment missing from resources map → fixed by default-empty-resources → affects commitments-v2 portfolio listing