Skip to content

Anthropic content_filter terminal is reported as 502 and retried by Codex #4312

Description

@luvs01

Client or integration

Codex App

Area

Streaming

Summary

An Anthropic filtered/refused stream is logged as HTTP 502 with Upstream incomplete: content_filter. Codex treats the response.incomplete terminal as a disconnected stream and retries the same sampling request up to five times. The provider decision should remain explicit, but the failure should not look like a transient transport outage or invite automatic repeated refusal requests.

Reproduction

  1. Stream an Anthropic-compatible response whose stop_reason is refusal/content_filter through /v1/responses.
  2. OpenCodex normalizes the stop reason to content_filter and emits response.incomplete.
  3. The usage record reports terminalStatus=incomplete, terminalSource=upstream, transportPhase=terminal_sse, status=502, and upstreamError=Upstream incomplete: content_filter.
  4. Codex logs stream disconnected before completion: Incomplete response returned, reason: content_filter, followed by retries 1/5 through 5/5.

Observed in two separate local conversations. No provider raw payload is retained for attachment, so this report does not assert whether the original vendor field was refusal or content_filter. The adapter and bridge mapping explain both forms. Preserve partial output and the actual refusal; do not replace it with false success, remove safety controls, or silently reroute to evade the decision.

Version

OpenCodex 2.51.0; Codex App executable 0.153.4.

Operating system

Windows 11 x64

Provider and model

anthropic / claude-opus-5, adapter=anthropic

Logs or error output

status=502 terminalStatus=incomplete terminalSource=upstream transportPhase=terminal_sse
Upstream incomplete: content_filter
stream disconnected - retrying sampling request (5/5 ...)
sampling_error=stream disconnected before completion: Incomplete response returned, reason: content_filter

Screenshots and supporting files

Source pointers: src/server/request-log.ts incompleteReasonLabel; src/adapters/anthropic.ts stop-reason mapping; src/bridge.ts incomplete terminal handling. A fixture-driven integration regression should assert one explicit non-retryable refusal terminal while preserving partial output and tool-call integrity. No billable live refusal replay is needed.

Redacted configuration

{"provider":"anthropic","model":"claude-opus-5","stream":true}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstreamingSSE, WebSocket, terminal stream frames

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions