BoundaryML/baml · error · io::Error
blob path has no parent
Error message
blob path has no parent
What it means
BlobStore::write_blob calls Path::parent() on the target blob path and errors if it returns None. A canonical content-addressed path (<root>/<algorithm>/<2-hex>/<digest>.blob) always has a parent, so this is a defensive guard; it would only trigger for a degenerate path such as a bare relative filename with no directory components.
Solutions
- Initialize the store with a proper non-empty root via BlobStore::new or ::with_boundary_dir (e.g. <dir>/blobs).
- Ensure the root path is absolute or correctly relative to the working directory before writing blobs.
- If it occurs with a valid store, treat it as a bug — the library should never reach this with normal path_for() output.
Example fix
// before
let store = BlobStore::new("")?; // degenerate path
// after
let store = BlobStore::with_boundary_dir("/path/to/run_dir")?; // <dir>/blobs Defensive patterns
Strategy: validation
Validate before calling
let root = Path::new(run_dir).join("blobs");
assert!(!root.as_os_str().is_empty(), "blob store root must be non-empty");
fs::create_dir_all(&root)?; Try / catch
match store.write_blob(&blob_ref) {
Ok(r) => r,
Err(e) if e.kind() == io::ErrorKind::InvalidInput => {
eprintln!("degenerate blob path — check BlobStore root: {e}");
return Err(e.into());
}
Err(e) => return Err(e.into()),
} Prevention
- Construct the store with BlobStore::with_boundary_dir or BlobStore::new with a valid directory.
- Ensure the run directory exists and the process has write access before writing blobs.
When it happens
Trigger: write_blob() where the resolved blob path has no parent directory component — effectively only if the blob store root itself is empty/degenerate or the path was reduced to a single file name.
Common situations: Constructing a BlobStore with an empty or malformed root so the joined path collapses, or misusing internal APIs to bypass path_for().
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- blob digest has no prefix
- a source root already exists at this path
- blob digest mismatch for
- blob size mismatch for
- block aware tail expression is not empty
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/6f8b3e20ce3fbece.
Report an issue: GitHub.
Appendix: source
Thrown at baml_language/crates/bex_events/src/value/artifact.rs:132
let prefix = digest.get(..2).ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidData, "blob digest has no prefix")
})?;
Ok(self
.root
.join(&blob_ref.algorithm)
.join(prefix)
.join(format!("{digest}.blob")))
}
pub fn write_blob(&self, bytes: &[u8]) -> io::Result<BlobRef> {
let blob_ref = BlobRef::sha256(bytes);
let path = self.path_for(&blob_ref)?;
if path.is_file() {
return Ok(blob_ref);
}
let parent = path.parent().ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidInput, "blob path has no parent")
})?;
fs::create_dir_all(parent)?;
let tmp_path = parent.join(format!(
".{}.{}.{}.tmp",
blob_ref.digest,
std::process::id(),
uuid::Uuid::new_v4()
));
{
let mut tmp = OpenOptions::new()
.write(true)
.create_new(true)
.open(&tmp_path)?;
tmp.write_all(bytes)?;
tmp.flush()?;
tmp.sync_all()?;
}
if path.is_file() {View on GitHub (pinned to bd85ce9dee)