BoundaryML/baml · error · io::Error

value record mixed capture loss metadata with body metadata

Error message

value record mixed capture loss metadata with body metadata

What it means

A capture_loss record must not carry value-body metadata. file_record_from_proto rejects a record where capture_loss is set together with metadata or a log_event, keeping capture-loss bookkeeping separate from event payloads. Raised as io::Error(InvalidData) when decoding the value file.

Source

Thrown at baml_language/crates/bex_events/src/value/read.rs:85

            || !record.body.is_empty()
            || has_log_event
            || has_capture_loss
            || record.blob.is_some())
    {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "value record mixed body metadata with lifecycle metadata",
        ));
    }
    if let Some(started) = record.run_started {
        return Ok(ValueFileRecord::RunStarted(started.try_into()?));
    }
    if let Some(completed) = record.run_completed {
        return Ok(ValueFileRecord::RunCompleted(completed.try_into()?));
    }
    if let Some(loss) = record.capture_loss {
        if record.metadata.is_some() || has_log_event {
            return Err(io::Error::new(
                io::ErrorKind::InvalidData,
                "value record mixed capture loss metadata with body metadata",
            ));
        }
        return Ok(ValueFileRecord::CaptureLoss(loss.try_into()?));
    }
    let metadata = record.metadata.ok_or_else(|| {
        io::Error::new(io::ErrorKind::InvalidData, "value record omitted metadata")
    })?;
    if let Some(log_event) = record.log_event {
        return Ok(ValueFileRecord::LogEvent(LogRecord {
            value_ref: metadata.try_into()?,
            body: record.body,
            blob_ref: record.blob.map(TryInto::try_into).transpose()?,
            event: log_event.try_into()?,
        }));
    }
    Err(io::Error::new(

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Regenerate the value file from the source run instead of patching the corrupted record.
  2. Fix the producer to write CaptureLoss records with only the capture_loss field populated.
  3. Verify no external tooling rewrites or merges records in the .bamlvalue file.

Example fix

// before
record.capture_loss = Some(loss);
record.metadata = Some(meta); // not allowed
// after
write_record(ValueFileRecord::CaptureLoss(loss));
Defensive patterns

Strategy: try-catch

Try / catch

match read_bamlvalue_from_bytes(&bytes) {
    Err(e) if e.to_string().contains("capture loss") => {
        eprintln!("capture-loss record contaminated with body fields: {e}");
        // treat file as corrupt; regenerate or skip record
    }
    other => other?,
}

Prevention

When it happens

Trigger: read_bamlvalue_from_bytes() on a record with capture_loss set plus record.metadata or record.log_event — indicates a corrupted file or a writer violating the record schema.

Common situations: Buggy custom writers, concurrent appenders interleaving records, external post-processing that merges fields, or format version mismatches.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/7862448db5c510e3. Report an issue: GitHub.