anthropics / anthropics/anthropic-sdk-python

Bedrock stream decoder drops SSE event types; type-less chunks construct as RawMessageStartEvent(message=None)

Abierto
#1,647 2 comentarios 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Python
Estrellas
3.9k
Forks
853
Merge medio
1 d 18 h
PR fusionados (30 d)
11

Descripción

### Summary

The Bedrock stream decoder (`anthropic/lib/bedrock/_stream_decoder.py`) hardcodes `ServerSentEvent(event="completion")` for every chunk, discarding the real event type. Downstream, the `"completion"` branch in `_streaming.py::__stream__` never backfills `data["type"]` (unlike the direct-SSE branch). Chunks without a `type` field — notably Bedrock's `amazon-bedrock-invocationMetrics` trailer — then hit non-validating `construct_type` against the stream-event union, which falls back to the **first union member** and yields `RawMessageStartEvent(message=None)` — an object that violates the SDK's own type contract (`message` is typed as non-optional).

### Reproduction (anthropic 0.105.2, offline)

```python
from anthropic._models import construct_type
from anthropic.types.beta import BetaRawMessageStreamEvent

event = construct_type(
value={"amazon-bedrock-invocationMetrics": {"inputTokenCount": 1}},
type_=BetaRawMessageStreamEvent,
)
print(type(event).__name__, event.message)
# BetaRawMessageStartEvent None
```

Any consumer that trusts the type annotations (e.g. `event.message.usage`) crashes with `AttributeError: 'NoneType' object has no attribute 'usage'`. We hit this in production via pydantic-ai's streaming path on `AsyncAnthropicBedrock` — intermittent 500s whenever a stream contained the invocationMetrics trailer.

### Expected

Either:
- the Bedrock decoder preserves/backfills the event type from the chunk payload's `type` field (the payloads do carry one for real events), and drops/ignores non-Messages chunks like `amazon-bedrock-invocationMetrics`, or
- stream-event construction validates and raises a clear error instead of silently producing a contract-violating first-union-member object.

### Notes

- Related but distinct from #1477 (decoder raises `ValueError` on error SSE events) — same file, different gap: this one is about *successful* streams containing type-less chunks.
- Direct (non-Bedrock) SSE is unaffected: that branch carries the event type and backfills `data["type"]`.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.