{"record":{"id":"380a9d4400e5b51b","repo":"BoundaryML/baml","slug":"trace-call-process-id-must-be-16-bytes-got","errorCode":null,"errorMessage":"trace call process id must be 16 bytes, got {}","messagePattern":"trace call process id must be 16 bytes, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_events/src/value/record.rs","lineNumber":262,"sourceCode":"    }\n}\n\nimpl From<&BlobRef> for crate::value::pb::BlobRefV1 {\n    fn from(value: &BlobRef) -> Self {\n        Self {\n            algorithm: value.algorithm.clone(),\n            digest: value.digest.clone(),\n            size_bytes: u64::try_from(value.size_bytes).unwrap_or(u64::MAX),\n        }\n    }\n}\n\nimpl TryFrom<crate::value::pb::TraceCallKeyV1> for TraceCallKey {\n    type Error = io::Error;\n\n    fn try_from(value: crate::value::pb::TraceCallKeyV1) -> Result<Self, Self::Error> {\n        let process_id: [u8; 16] = value.process_id.as_slice().try_into().map_err(|_| {\n            io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"trace call process id must be 16 bytes, got {}\",\n                    value.process_id.len()\n                ),\n            )\n        })?;\n        Ok(Self {\n            process_euid: ProcessEuid(process_id),\n            engine_id: EngineId(value.engine_id),\n            thread_id: BexThreadId(value.thread_id),\n            call_id: BexCallId(value.call_id),\n        })\n    }\n}\n\nimpl From<TraceCallKey> for crate::value::pb::TraceCallKeyV1 {\n    fn from(value: TraceCallKey) -> Self {","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_events/src/value/record.rs#L244-L280","documentation":"TraceCallKeyV1.process_id must be exactly 16 bytes (a 128-bit UUID-style identifier) to convert into the internal TraceCallKey's [u8; 16]. The TryFrom impl rejects any other length, including the length actually received, via InvalidData with this formatted message.","triggerScenarios":"Decoding a TraceCallKeyV1 whose process_id field is empty, truncated by corruption, or written with a different-length ID (e.g. 8-byte, 32-byte hex string) by an incompatible producer.","commonSituations":"Version skew where an older/newer writer uses a different process-id representation, manual proto construction with placeholder IDs, or byte-level file corruption.","solutions":["Fix the producer to always emit a 16-byte process_id (e.g. a UUID v4 as raw bytes)","Pad/truncate or regenerate IDs in a migration tool when converting legacy streams","Validate process_id.len() == 16 at the writer boundary before serializing","Inspect the reported length in the message to identify which producer/version wrote the bad ID"],"exampleFix":"// before\nlet process_id = value.process_id; // arbitrary-length Vec<u8>\n// after\nlet mut process_id = [0u8; 16];\nif value.process_id.len() == 16 { process_id.copy_from_slice(&value.process_id); } else { return Err(...); }","handlingStrategy":"validation","validationCode":"fn is_uuid16(id: &[u8]) -> bool { id.len() == 16 }","typeGuard":"fn as_process_id(bytes: &[u8]) -> Option<[u8; 16]> { bytes.try_into().ok() }","tryCatchPattern":"TraceCallKey::try_from(raw).map_err(|e| { warn!(\"bad process id: {e}\"); CorruptionKind::BadProcessId.into() })","preventionTips":["Generate process IDs as 16-byte UUIDs at the producer","Assert id length in producer unit tests","Include a format/version byte scheme if ids may evolve"],"tags":["rust","protobuf","deserialization","identifier"],"backgroundTag":"invalid-identifier-format","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}