{"record":{"id":"2bce733f99aa9636","repo":"BoundaryML/baml","slug":"capture-loss-omitted-reason","errorCode":null,"errorMessage":"capture loss omitted reason","messagePattern":"capture loss omitted reason","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"baml_language/crates/bex_events/src/value/record.rs","lineNumber":367,"sourceCode":"}\n\nimpl TryFrom<crate::value::pb::CaptureLossV1> for CaptureLossRecord {\n    type Error = io::Error;\n\n    fn try_from(value: crate::value::pb::CaptureLossV1) -> Result<Self, Self::Error> {\n        let kind = match value.kind() {\n            crate::value::pb::CaptureLossKind::Log => CaptureLossKind::Log,\n            crate::value::pb::CaptureLossKind::Unspecified => {\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    \"capture loss omitted kind\",\n                ));\n            }\n        };\n        let reason = match value.reason() {\n            crate::value::pb::CaptureLossReason::QueueFull => CaptureLossReason::QueueFull,\n            crate::value::pb::CaptureLossReason::Unspecified => {\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    \"capture loss omitted reason\",\n                ));\n            }\n        };\n        Ok(Self {\n            kind,\n            reason,\n            skipped_count: value.skipped_count,\n            call: value.call.map(TryInto::try_into).transpose()?,\n            message: value.message,\n            timestamp_ms: value.timestamp_ms,\n        })\n    }\n}\n\nimpl From<&CaptureLossRecord> for crate::value::pb::CaptureLossV1 {\n    fn from(value: &CaptureLossRecord) -> Self {","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/baml_language/crates/bex_events/src/value/record.rs#L349-L385","documentation":"CaptureLossV1.reason must be explicitly set (currently QueueFull) explaining why capture was lost; proto3's default Unspecified is rejected by the TryFrom conversion with InvalidData and this message. A loss record without a reason provides no actionable signal, so the reader treats it as malformed.","triggerScenarios":"Decoding a CaptureLossV1 whose reason field was left unset by the writer, or dropped when the message was rebuilt/copied by migration or proxy code.","commonSituations":"Older writers before the reason field existed, manually constructed loss records missing the enum setter, schema migrations defaulting new enum fields to Unspecified.","solutions":["Fix the producer to always set reason (e.g. CaptureLossReason::QueueFull) on loss records","Set the enum explicitly when constructing the proto manually","Apply a decode-time default (Unspecified -> QueueFull) if your contract only produces queue-full losses","Align writer/reader versions and migrate legacy streams lacking the reason field"],"exampleFix":"// before\nlet loss = pb::CaptureLossV1 { kind: ..., ..Default::default() };\n// after\nlet loss = pb::CaptureLossV1 { kind: ..., reason: pb::CaptureLossReason::QueueFull as i32, ..Default::default() };","handlingStrategy":"validation","validationCode":"fn loss_reason_set(loss: &pb::CaptureLossV1) -> bool { loss.reason() != pb::CaptureLossReason::Unspecified }","typeGuard":"fn valid_loss_reason(loss: &pb::CaptureLossV1) -> bool { matches!(loss.reason(), pb::CaptureLossReason::QueueFull) }","tryCatchPattern":"CaptureLossRecord::try_from(loss).map_err(|e| if e.to_string().contains(\"omitted reason\") { default_reason_record(loss) } else { e })","preventionTips":["Set the reason enum explicitly whenever emitting a capture-loss record","Add producer tests asserting loss records carry both kind and reason","Keep writer/reader enum definitions in sync via a shared schema"],"tags":["rust","protobuf","deserialization","enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}