BoundaryML/baml · error · io::Error

value record mixed body metadata with lifecycle metadata

Error message

value record mixed body metadata with lifecycle metadata

What it means

file_record_from_proto rejects a record that has lifecycle metadata (run_started or run_completed) together with any body content: metadata, non-empty body, log_event, capture_loss, or blob. Lifecycle records must stand alone; mixing them with payload data violates the value-file record schema. Raised as io::Error(InvalidData) during read_bamlvalue_from_bytes.

Source

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

    let has_run_started = record.run_started.is_some();
    let has_run_completed = record.run_completed.is_some();
    let has_lifecycle = has_run_started || has_run_completed;
    let has_log_event = record.log_event.is_some();
    let has_capture_loss = record.capture_loss.is_some();
    if has_run_started && has_run_completed {
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "value record mixed run_started with run_completed lifecycle metadata",
        ));
    }
    if has_lifecycle
        && (record.metadata.is_some()
            || !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()?));

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Regenerate the value file; treat it as corrupted rather than repairing bytes by hand.
  2. Fix the writer to emit lifecycle metadata in its own record with all other fields unset.
  3. Confirm the file was written by a compatible version of bex_events and not post-processed externally.

Example fix

// before
record.run_started = Some(started);
record.metadata = Some(meta); // lifecycle + body
// after
write_record(ValueFileRecord::RunStarted(started));
write_record(ValueFileRecord::LogEvent(LogRecord { .. }));
Defensive patterns

Strategy: try-catch

Try / catch

let value = read_bamlvalue_from_bytes(&bytes).map_err(|e| {
    if e.to_string().contains("mixed body metadata with lifecycle") {
        eprintln!("value file record schema violated: {e}");
    }
    e
})?;

Prevention

When it happens

Trigger: Reading a value file record where a run_started/run_completed oneof is set alongside metadata/body/log_event/capture_loss/blob fields — produced by a buggy writer, corrupted file, or incompatible format version.

Common situations: External tools rewriting event files incorrectly, concurrent appends interleaving two records into one, or writing with an older/newer schema that packed fields differently.

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/5e2cd6d253e25358. Report an issue: GitHub.