Skip to content

bug(dp): upstream 4xx forwarding loses the upstream-side error.code field #322

Description

@moonming

Summary

Phase 1 of the E2E matrix series (#328) added a scenario asserting that an upstream 4xx response with an OpenAI-shape error envelope is forwarded as-is to the customer. The DP forwards the right status (429) and the right `error.message`, but drops the `error.code` field.

Repro

Phase 1 spec, scenario "upstream 4xx is forwarded as-is with the OpenAI-shape body intact":

```
expect: "forced_429"
received: undefined

626 | expect(err?.code, 'code preserved').toBe('forced_429');
```

mock-llm returns:
```json
{
"error": {
"message": "mock-llm forced status 429",
"type": "upstream_test_fixture",
"code": "forced_429"
}
}
```

DP forwards to customer:

  • ✓ status 429
  • ✓ `error.message` (preserved)
  • ✗ `error.code` (dropped — assertion fails)
  • ? `error.type` (not asserted)

Customer impact

OpenAI's official error envelope has 4 fields: `message`, `type`, `code`, `param`. SDKs and downstream tools (Langchain, LiteLLM-compat shims, Helicone, etc.) commonly switch on `code` to decide retry logic — `rate_limit_exceeded` vs `insufficient_quota` vs `model_not_found` all carry different recovery paths. Dropping `code` from the forwarded envelope silently downgrades every customer's retry intelligence when an upstream returns a coded 4xx.

Expected behavior

For upstream 4xx pass-through (the contract Phase 1's `error_envelope` override pins as the default), the DP should forward the upstream's error envelope verbatim — all four OpenAI fields (`message`, `type`, `code`, `param`) when present.

Test impact

Phase 1 matrix scenario currently fails on the `code` assertion. To unblock Phase 1 merge, the assertion will be loosened to a comment + issue link pointing here; once this bug is fixed, the assertion gets tightened back.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions