can1357/oh-my-pi · error · AnthropicStreamEnvelopeError

received ${event.type} before message_start

Error message

received ${event.type} before message_start

What it means

This AnthropicStreamEnvelopeError is thrown when a decoded stream event of a non-ignorable type arrives before the required `message_start` frame. The Anthropic streaming protocol mandates message_start first; the library tolerates a small set of preamble events but any other event at that point means the stream is malformed or not a real Anthropic event stream.

Source

Thrown at packages/ai/src/providers/anthropic.ts:2331

									const served = fallbackServedModelFromUsage(startUsage);
									if (served) output.model = served;
									if (!calculateFallbackTurnCost(model, output.usage, startUsage)) {
										calculateCost(model, output.usage);
									}
								} else {
									calculateCost(model, output.usage);
								}
							} else {
								reportAnthropicEnvelopeAnomaly("message_start missing usage");
							}
							continue;
						}

						if (!sawMessageStart) {
							if (shouldIgnoreAnthropicPreambleEvent(event.type)) {
								continue;
							}
							throw new AIError.AnthropicStreamEnvelopeError(`received ${event.type} before message_start`);
						}

						if (event.type === "content_block_start") {
							if (sawTerminalEnvelope) {
								reportAnthropicEnvelopeAnomaly(`received ${event.type} after terminal stop signal`);
								continue;
							}
							if (openBlocks.has(event.index)) {
								reportAnthropicEnvelopeAnomaly(`duplicate content_block_start index ${event.index}`);
								continue;
							}
							if (sawSplicedEnvelope && closedBlockIndexes.has(event.index)) {
								// A spliced envelope replaying an index this stream already
								// completed would append duplicate text/tool calls; consume its
								// events silently instead.
								reportAnthropicEnvelopeAnomaly(
									`replayed content_block_start index ${event.index} after duplicate message_start`,
								);

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the first raw SSE events from the endpoint (enable onSseEvent/raw event capture) to see what precedes message_start.
  2. Fix or bypass the gateway/proxy mangling the event order so message_start is sent first.
  3. Check the configured Anthropic API version and endpoint against the documented streaming protocol.
  4. If it's a known preamble event your gateway emits, verify shouldIgnoreAnthropicPreambleEvent coverage / upgrade the library.
Defensive patterns

Strategy: retry

Validate before calling

// Validate the endpoint before relying on streaming:
const probe = await fetch(`${baseUrl}/v1/messages`, { method: "POST", headers, body: JSON.stringify({ ...minimalRequest, stream: true, max_tokens: 1 }) });
if (!probe.headers.get("content-type")?.includes("text/event-stream")) {
  throw new Error("Endpoint does not return an SSE stream; gateway will produce malformed events.");
}

Try / catch

try {
  yield* iterateAnthropicEvents(response, signal, onSseEvent);
} catch (err) {
  if (err instanceof AIError.AnthropicStreamEnvelopeError && /before message_start/.test(err.message)) {
    // retryable envelope error: retry the request once; keep raw SSE (onSseEvent) for diagnosis
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: SSE iteration yields e.g. content_block_start/delta/stop, message_delta, or an unknown event type while sawMessageStart is still false and shouldIgnoreAnthropicPreambleEvent does not whitelist the type — typically when the endpoint sends nonstandard frames or an error payload as the first event.

Common situations: Proxy/gateway (LiteLLM, Bedrock wrappers) that reorders or injects events; endpoints emitting error JSON as the first SSE event; API version drift changing event ordering; replayed/spliced streams from caches.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/b8f3251c43d0d18b. Report an issue: GitHub.