Skip to content

fix(instrumentation-botocore): do not mark HTTP 3xx responses as span errors#4653

Open
stark256-spec wants to merge 2 commits into
open-telemetry:mainfrom
stark256-spec:fix/botocore-304-not-error
Open

fix(instrumentation-botocore): do not mark HTTP 3xx responses as span errors#4653
stark256-spec wants to merge 2 commits into
open-telemetry:mainfrom
stark256-spec:fix/botocore-304-not-error

Conversation

@stark256-spec

@stark256-spec stark256-spec commented Jun 3, 2026

Copy link
Copy Markdown

Description

Fixes #4633

What changed and why

botocore raises ClientError for HTTP 3xx responses such as 304 Not Modified (returned when using conditional S3 requests with IfNoneMatch or IfModifiedSince). The instrumentor was calling extension.on_error for every ClientError regardless of HTTP status, and the span context manager's default set_status_on_exception behaviour then set StatusCode.ERROR as the exception propagated out.

304 Not Modified and other 3xx responses are normal, expected outcomes — not errors. Marking them as errors pollutes error-rate dashboards and triggers false alerts.

Fix: check HTTPStatusCode from the error response metadata before invoking on_error. For HTTP < 400, explicitly set StatusCode.OK on the span (which the OTel spec guarantees cannot be overridden to ERROR by the context manager) and skip on_error. For 4xx/5xx the existing behaviour is unchanged.

Applied to both BotocoreInstrumentor and AiobotocoreInstrumentor.

Testing

  • Existing botocore unit tests pass
  • New test covering 304 response not marked as error (to be added — happy to add if maintainers confirm the approach)

…create and AsyncMessages.stream

AnthropicInstrumentor only patched the synchronous Messages.create and
Messages.stream methods. AsyncAnthropic clients use AsyncMessages, so
async calls produced no spans at all.

Add two new patch functions mirroring the sync variants:

- async_messages_create: awaits wrapped(), detects AsyncStream responses
  and wraps them in the existing AsyncMessagesStreamWrapper
- async_messages_stream: wraps the async stream manager in the existing
  AsyncMessagesStreamManagerWrapper

Wire both into _instrument() with wrap_function_wrapper targeting
AsyncMessages.create and AsyncMessages.stream, and add the
corresponding unwrap() calls in _uninstrument().

The AsyncMessagesStreamWrapper and AsyncMessagesStreamManagerWrapper
classes were already present in wrappers.py but were not being used.

Fixes open-telemetry#4497

Assisted-by: Claude Sonnet 4.5
@stark256-spec stark256-spec requested a review from a team as a code owner June 3, 2026 16:16
@github-actions github-actions Bot added the gen-ai Related to generative AI label Jun 3, 2026
botocore raises ClientError for HTTP 3xx responses such as 304 Not
Modified (returned when using conditional requests with IfNoneMatch or
IfModifiedSince). The instrumentor was calling extension.on_error and
allowing the span context manager to set StatusCode.ERROR for all
ClientError exceptions regardless of HTTP status.

304 and other 3xx responses are expected, non-error outcomes. Marking
them as errors pollutes error-rate dashboards and triggers false alerts.

Fix: extract the HTTPStatusCode from the error response metadata before
deciding whether to invoke on_error. For HTTP status < 400, explicitly
set StatusCode.OK on the span (which prevents the context manager's
automatic ERROR status from overriding it) and skip on_error. For 4xx
and 5xx the existing behaviour is unchanged.

The fix is applied to both BotocoreInstrumentor and
AiobotocoreInstrumentor (identical except/raise blocks).

Fixes open-telemetry#4633
@stark256-spec stark256-spec force-pushed the fix/botocore-304-not-error branch from 52a4976 to 8839991 Compare June 3, 2026 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gen-ai Related to generative AI

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Botocore instrumentation incorrectly marks S3 304 Not Modified as span error

2 participants