astrid-runtime/astrid · error
capsule path is not valid UTF-8
Error message
capsule path is not valid UTF-8
What it means
`append_entry` requires the capsule-relative path to be valid UTF-8 so it can be written into the tar header. If the relative path contains bytes that are not valid UTF-8 (possible on Unix where paths are arbitrary bytes), `relative.to_str()` returns `None` and this error is raised. The library refuses rather than writing a tar entry with an ambiguous name.
Source
Thrown at crates/astrid-capsule-install/src/storage.rs:861
let entry = entry.with_context(|| format!("read child of {}", path.display()))?;
let name = entry.path();
let metadata = fs::symlink_metadata(&name)
.with_context(|| format!("inspect capsule source entry {}", name.display()))?;
children.push((name, metadata));
}
children.sort_by(|left, right| left.0.cmp(&right.0));
Ok(children)
}
fn append_entry(
builder: &mut Builder<GzEncoder<Vec<u8>>>,
root: &Path,
relative: &Path,
metadata: &Metadata,
) -> anyhow::Result<()> {
let path = relative
.to_str()
.ok_or_else(|| anyhow::anyhow!("capsule path is not valid UTF-8"))?;
if path.starts_with('/') || path.split('/').any(|part| part == ".." || part.is_empty()) {
bail!("capsule path is not canonical: {path}");
}
let mut header = Header::new_gnu();
header.set_uid(0);
header.set_gid(0);
header.set_mtime(0);
header.set_mode(if metadata.is_dir() { 0o755 } else { 0o644 });
if metadata.is_dir() {
header.set_entry_type(EntryType::Directory);
header.set_size(0);
header.set_cksum();
builder
.append_data(&mut header, path, io::empty())
.with_context(|| format!("append capsule directory {path}"))?;
} else {
let mut file =
File::open(root.join(relative)).with_context(|| format!("open capsule file {path}"))?;View on GitHub (pinned to affd8760f4)
Solutions
- Find and rename the offending file(s) to valid UTF-8 names, e.g. with `convmv -f latin1 -t utf8 -r <dir>` or `find <dir> | grep -Pv '^[\x00-\x7F\x80-\xF7]*$'` to locate them
- Recreate the capsule source from a clean checkout that only contains UTF-8 filenames
- If the tooling is under your control, validate entry names at intake time and reject/normalize non-UTF-8 names before archiving
Example fix
// before $ ls my-capsule/src caf???.rs # Latin-1 encoded name // after $ convmv -f latin1 -t utf8 --notest -r my-capsule canonical_capsule_archive(home, &capsule_root, ...)?;
Defensive patterns
Strategy: validation
Validate before calling
fn assert_all_names_utf8(root: &Path) -> anyhow::Result<()> {
for entry in walkdir::WalkDir::new(root) {
let entry = entry?;
let rel = entry.path().strip_prefix(root)?;
anyhow::ensure!(rel.to_str().is_some(),
"non-UTF-8 path in capsule: {}", entry.path().display());
}
Ok(())
}
assert_all_names_utf8(&capsule_root)?; Type guard
fn is_utf8_path(p: &Path) -> bool { p.to_str().is_some() } Try / catch
match canonical_capsule_archive(home, &root, ...) {
Err(e) if e.to_string().contains("not valid UTF-8") => {
// locate offending name and rename/normalize, then retry
}
Err(e) => return Err(e),
Ok(a) => a,
} Prevention
- Run under a UTF-8 locale (LC_ALL=C.UTF-8) when generating capsule files
- Normalize filenames at intake: reject or transcode non-UTF-8 names when ingesting user archives
- Use convmv or similar to normalize legacy-encoded trees before packing
- Add a pre-archive lint that walks the tree and asserts Path::to_str().is_some() for every entry
When it happens
Trigger: Calling `canonical_capsule_archive` over a source tree that contains a file or directory whose name includes non-UTF-8 bytes (e.g. Latin-1 encoded filenames from an old archive extraction, or filenames created by non-UTF-8 locale tools).
Common situations: Capsules packed on machines with non-UTF-8 filesystem locales; files unzipped from legacy ZIP archives with CP437/Latin-1 name encoding; files created with `touch $'\xff'` in scripts.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- legacy capsule authority entry has a non-UTF-8 name: {}
- capsule path escaped source root
- legacy capsule entry has a non-UTF-8 name
- capsule projection path is not UTF-8: {}
- layout destination path is not portable UTF-8: {error}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/bf44441b33a7d345.
Report an issue: GitHub.