BoundaryML/baml · error · io::Error

history boundary for project {} omitted canonical boundary i

Error message

history boundary for project {} omitted canonical boundary id

What it means

When segment headers yield no consistent boundary ID, the fallback derives the canonical ID from the directory name; if that also fails (no fallback dir or an unparseable dir name), InvalidData is returned, including the run's project_id. The library refuses to open a boundary whose identity cannot be established from headers or directory name.

Source

Thrown at baml_language/crates/bex_events/src/history/mod.rs:626

) -> io::Result<BoundaryId> {
    if let Some(first) = header_boundary_ids.first().copied() {
        if header_boundary_ids.iter().all(|id| *id == first) {
            return Ok(first);
        }
        return Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!(
                "history boundary {} has inconsistent value segment boundary ids",
                fallback_dir
                    .map(|dir| dir.display().to_string())
                    .unwrap_or_else(|| "byte segments".to_string())
            ),
        ));
    }
    fallback_dir
        .and_then(boundary_id_from_dir_name)
        .ok_or_else(|| {
            io::Error::new(
                io::ErrorKind::InvalidData,
                format!(
                    "history boundary for project {} omitted canonical boundary id",
                    started.request.project_id.0
                ),
            )
        })
}

fn boundary_id_from_header(bytes: &[u8]) -> io::Result<BoundaryId> {
    let bytes: [u8; 16] = bytes.try_into().map_err(|_| {
        io::Error::new(
            io::ErrorKind::InvalidData,
            format!(
                ".bamlvalue header boundary id must be 16 bytes, got {}",
                bytes.len()
            ),
        )

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Ensure segment headers carry a consistent boundary ID so the fallback isn't needed.
  2. If relying on the fallback, name the directory with the boundary's wire-format ID (as to_wire_string produces).
  3. Pass the original, unrenamed boundary directory when opening from disk.
  4. Cross-check the project_id in the message against the run you intend to open.

Example fix

// before
let dir = std::env::temp_dir().join("scratch");
let id = boundary_id_from_header_or_fallback(&segs, Some(&dir), &started)?;
// after
let dir = std::env::temp_dir().join(started.request.run_id.to_wire_string());
let id = boundary_id_from_header_or_fallback(&segs, Some(&dir), &started)?;
Defensive patterns

Strategy: validation

Validate before calling

let dir = match fallback_dir {
    Some(d) => d,
    None => return Err("need a boundary-named directory when headers lack IDs".into()),
};
if BoundaryId::parse_from_dir_name(&dir).is_none() {
    return Err(format!("dir name {} is not a boundary id", dir.display()));
}

Try / catch

match open_boundary_from_segments(fallback_dir.as_deref(), &segments) {
    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => {
        Err(ReplayError::UnidentifiableBoundary(project_id))
    }
    other => other,
}

Prevention

When it happens

Trigger: open_boundary_from_segments given byte segments with inconsistent/absent header IDs and either no fallback directory or a directory name that isn't a valid boundary-ID name, for the given project.

Common situations: Replaying from in-memory segments with no directory context; renaming a boundary directory with a non-wire-format name; passing a scratch dir whose name doesn't encode the boundary ID.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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