{"record":{"id":"b8f3251c43d0d18b","repo":"can1357/oh-my-pi","slug":"received-event-type-before-message-start","errorCode":null,"errorMessage":"received ${event.type} before message_start","messagePattern":"received (.+?) before message_start","errorType":"exception","errorClass":"AnthropicStreamEnvelopeError","httpStatus":null,"severity":"error","filePath":"packages/ai/src/providers/anthropic.ts","lineNumber":2331,"sourceCode":"\t\t\t\t\t\t\t\t\tconst served = fallbackServedModelFromUsage(startUsage);\n\t\t\t\t\t\t\t\t\tif (served) output.model = served;\n\t\t\t\t\t\t\t\t\tif (!calculateFallbackTurnCost(model, output.usage, startUsage)) {\n\t\t\t\t\t\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treportAnthropicEnvelopeAnomaly(\"message_start missing usage\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!sawMessageStart) {\n\t\t\t\t\t\t\tif (shouldIgnoreAnthropicPreambleEvent(event.type)) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthrow new AIError.AnthropicStreamEnvelopeError(`received ${event.type} before message_start`);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (event.type === \"content_block_start\") {\n\t\t\t\t\t\t\tif (sawTerminalEnvelope) {\n\t\t\t\t\t\t\t\treportAnthropicEnvelopeAnomaly(`received ${event.type} after terminal stop signal`);\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (openBlocks.has(event.index)) {\n\t\t\t\t\t\t\t\treportAnthropicEnvelopeAnomaly(`duplicate content_block_start index ${event.index}`);\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (sawSplicedEnvelope && closedBlockIndexes.has(event.index)) {\n\t\t\t\t\t\t\t\t// A spliced envelope replaying an index this stream already\n\t\t\t\t\t\t\t\t// completed would append duplicate text/tool calls; consume its\n\t\t\t\t\t\t\t\t// events silently instead.\n\t\t\t\t\t\t\t\treportAnthropicEnvelopeAnomaly(\n\t\t\t\t\t\t\t\t\t`replayed content_block_start index ${event.index} after duplicate message_start`,\n\t\t\t\t\t\t\t\t);","sourceCodeStart":2313,"sourceCodeEnd":2349,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/ai/src/providers/anthropic.ts#L2313-L2349","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the first raw SSE events from the endpoint (enable onSseEvent/raw event capture) to see what precedes message_start.","Fix or bypass the gateway/proxy mangling the event order so message_start is sent first.","Check the configured Anthropic API version and endpoint against the documented streaming protocol.","If it's a known preamble event your gateway emits, verify shouldIgnoreAnthropicPreambleEvent coverage / upgrade the library."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Validate the endpoint before relying on streaming:\nconst probe = await fetch(`${baseUrl}/v1/messages`, { method: \"POST\", headers, body: JSON.stringify({ ...minimalRequest, stream: true, max_tokens: 1 }) });\nif (!probe.headers.get(\"content-type\")?.includes(\"text/event-stream\")) {\n  throw new Error(\"Endpoint does not return an SSE stream; gateway will produce malformed events.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  yield* iterateAnthropicEvents(response, signal, onSseEvent);\n} catch (err) {\n  if (err instanceof AIError.AnthropicStreamEnvelopeError && /before message_start/.test(err.message)) {\n    // retryable envelope error: retry the request once; keep raw SSE (onSseEvent) for diagnosis\n  } else {\n    throw err;\n  }\n}","preventionTips":["Capture raw SSE events (onSseEvent) in development to spot gateways emitting nonstandard first frames.","Ensure proxies forward Anthropic error frames as SSE rather than replacing the stream body.","Pin compatible API versions on both client and gateway.","Prefer gateways with documented Anthropic streaming passthrough (no event rewriting)."],"tags":["streaming","sse","anthropic","protocol-violation"],"backgroundTag":"malformed-stream-events","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}