{"record":{"id":"49f8e91c84fc58ca","repo":"headroomlabs-ai/headroom","slug":"bedrock-eventstream-parse-failed","errorCode":"bedrock_eventstream_parse_failed","errorMessage":"implausible prelude lengths: total_length={total_length}, headers_length={headers_length}","messagePattern":"implausible prelude lengths: total_length=(.+?), headers_length=(.+?)","errorType":"exception","errorClass":"ParseError::ImplausiblePreludeLengths","httpStatus":null,"severity":"error","filePath":"crates/headroom-proxy/src/bedrock/eventstream.rs","lineNumber":149,"sourceCode":"        self.headers.get(\":event-type\").and_then(|v| v.as_str())\n    }\n\n    /// Read the `:message-type` header as a string. Bedrock uses\n    /// `event` (data frames) vs `exception` (synchronous errors).\n    pub fn message_type(&self) -> Option<&str> {\n        self.headers.get(\":message-type\").and_then(|v| v.as_str())\n    }\n}\n\n/// Errors surfaced by the parser. Per project rules these are\n/// structured (not `String`) so the handler can dispatch on them.\n#[derive(Debug, Error)]\npub enum ParseError {\n    /// `total_length` smaller than the minimum a well-formed message\n    /// requires (12-byte prelude, headers block, 4-byte trailing CRC).\n    /// Wire-format violation; AWS would never emit this. Surfaced\n    /// loudly so the handler can 5xx and log it.\n    #[error(\n        \"implausible prelude lengths: total_length={total_length}, headers_length={headers_length}\"\n    )]\n    ImplausiblePreludeLengths {\n        total_length: u32,\n        headers_length: u32,\n    },\n    /// `total_length` exceeds the configured `max_message_bytes` cap.\n    /// The cap defaults to 32 MiB; configurable via\n    /// [`EventStreamParser::with_max_message_bytes`].\n    #[error(\"message too large: total_length={total_length} cap={cap}\")]\n    MessageTooLarge { total_length: u32, cap: usize },\n    /// CRC32 of the first 8 bytes of the prelude did not match the\n    /// 9th-12th bytes. Indicates corruption (in-flight bit-flip,\n    /// truncated chunk, or — if persistent — wire-format version skew).\n    #[error(\"prelude CRC mismatch: expected={expected:#010x} got={got:#010x}\")]\n    PreludeCrcMismatch { expected: u32, got: u32 },\n    /// CRC32 of the entire message body did not match the trailing\n    /// 4-byte CRC. Indicates the message bytes were corrupted in","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/crates/headroom-proxy/src/bedrock/eventstream.rs#L131-L167","documentation":"MemoryHandler initialization rejected the configured backend string (memory_handler.py:443). Only 'local' and 'qdrant-neo4j' are recognized; anything else — 'qdrant', 'sqlite', 'chroma', 'none', empty-but-set, or a typo — raises ValueError during initialize(), which surfaces at startup or first memory use.","triggerScenarios":"Setting memory_backend/memory-backend config or CLI flag to a nonexistent backend name; renaming between versions (e.g. older 'qdrant' vs current 'qdrant-neo4j'); env-derived values with whitespace or wrong casing.","commonSituations":"Upgrading headroom and reusing an old config file; copy-pasting backend names from docs of a different version; disabling intent expressed as 'none' or 'off' which is not a valid backend.","solutions":["Set the backend to 'local' (embedded) or 'qdrant-neo4j' (external vector+graph stack)","Check for typos/case in your config file, CLI flag, or environment variable before the memory handler initializes","If you meant to disable memory, use the memory disable option rather than an invalid backend string"],"exampleFix":"# before (config)\nmemory_backend = \"qdrant\"\n\n# after\nmemory_backend = \"qdrant-neo4j\"","handlingStrategy":"validation","validationCode":"VALID_BACKENDS = {\"local\", \"qdrant-neo4j\"}\nif config.get(\"backend\") not in VALID_BACKENDS:\n    raise SystemExit(f\"memory backend must be one of {sorted(VALID_BACKENDS)}, got {config.get('backend')!r}\")","typeGuard":"from typing import Literal, TypeGuard\nMemoryBackend = Literal[\"local\", \"qdrant-neo4j\"]\ndef is_valid_backend(v: str) -> TypeGuard[MemoryBackend]:\n    return v in (\"local\", \"qdrant-neo4j\")","tryCatchPattern":null,"preventionTips":["Re-check backend names after upgrading headroom","Validate config files in CI before deploy"],"tags":["configuration","memory","startup","validation"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}