astrid-runtime/astrid · error
sandbox {label} is not valid UTF-8: {}
Error message
sandbox {label} is not valid UTF-8: {} What it means
validate_sandbox_str requires the path to be valid UTF-8 because sandbox profiles are text formats. Non-UTF-8 paths (common on Unix, where paths are arbitrary bytes) cannot be safely interpolated, so the function rejects them with InvalidInput naming the label and the lossily-displayed path.
Source
Thrown at crates/astrid-workspace/src/sandbox/mod.rs:26
#[cfg(target_os = "macos")]
mod seatbelt;
/// Validate a path for safe interpolation into sandbox profiles (SBPL/bwrap).
///
/// Rejects relative paths, non-UTF-8, double-quote, backslash, and null byte -
/// all of which can break or bypass sandbox profile syntax.
fn validate_sandbox_str<'a>(path: &'a Path, label: &str) -> io::Result<&'a str> {
if !path.is_absolute() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"sandbox {label} must be an absolute path, got: {}",
path.display()
),
));
}
let s = path.to_str().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
format!("sandbox {label} is not valid UTF-8: {}", path.display()),
)
})?;
if s.contains(['"', '\\', '\0']) {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"sandbox {label} contains forbidden characters (double-quote, backslash, or null): {}",
path.display()
),
));
}
Ok(s)
}
/// A host-verified, read-only file the sandbox materializes inside a spawned
/// child. `source` is the host-owned path the verified snapshot already livesView on GitHub (pinned to affd8760f4)
Solutions
- Rename the offending file/directory to a UTF-8 name
- If the path came from OsString bytes, transcode to UTF-8 (or reject) before calling the sandbox API
- Ensure the process locale/encoding producing the path emits UTF-8 (e.g. LC_ALL/LANG settings)
- Reject non-UTF-8 paths at ingestion and report them to the user instead of passing them through
Example fix
// before let p = PathBuf::from(std::ffi::OsString::from_vec(raw_bytes)); wrap_with_process_paths(&ws, &[p], &[])?; // after let s = std::str::from_utf8(&raw_bytes)?; let p = PathBuf::from(s); wrap_with_process_paths(&ws, &[p], &[])?;
Defensive patterns
Strategy: validation
Validate before calling
fn ensure_utf8(p: &Path) -> io::Result<()> { p.to_str().map(|_| ()).ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, format!("non-UTF-8 path: {}", p.display()))) } Type guard
fn is_utf8_path(p: &Path) -> bool { p.to_str().is_some() } Try / catch
match validate_result { Err(e) if e.to_string().contains("not valid UTF-8") => { /* rename/transcode the file or exclude it from the sandbox */ }, other => other, } Prevention
- Require UTF-8 filenames in your application (reject others at creation)
- Set UTF-8 locales in environments that produce the paths
- Transcode OsStr bytes to UTF-8 (or skip) before sandbox configuration
When it happens
Trigger: Calling wrap_with_process_paths, validate_all_paths, or build_seatbelt_prefix with a Path built from raw bytes that are not valid UTF-8 (e.g. OsStr::from_bytes with latin-1 or mixed-encoding bytes).
Common situations: Files created with filenames in a legacy locale encoding; paths received over IPC or from archives with non-UTF-8 names; systems whose filesystem encoding differs from UTF-8.
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
- sandbox {label} must be an absolute path, got: {}
- sandbox {label} contains forbidden characters (double-quote,
- process read path does not exist: {}
- process write path does not exist: {}
- capsule source is neither a directory nor a regular file: {}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/921ca826c889df78.
Report an issue: GitHub.