unicity-aos/aos-ce · error · io::Error

product release runtime bin contains a non-UTF-8 entry

Error message

product release runtime bin contains a non-UTF-8 entry

What it means

validate_release_runtime_bin enumerates the release runtime bin directory and converts each entry's file name to a Rust String; an entry whose name is not valid UTF-8 triggers this InvalidInput error. The validator needs String names to compare against RUNTIME_EXECUTABLE_NAMES, so non-UTF-8 entries are rejected.

Solutions

  1. Remove or rename the non-UTF-8 entry in the release runtime bin directory
  2. Re-extract the release archive on a UTF-8 locale/filesystem so names decode correctly
  3. Validate directory contents with entry.file_name().to_str().is_some() before migrating

Example fix

// before
$ ls bin
foobar  # non-UTF-8 entry

// after
$ rm bin/foobar   # or re-extract the release cleanly
$ ls bin
runtime-core
Defensive patterns

Strategy: validation

Validate before calling

fn bin_names_utf8(dir: &std::path::Path) -> bool {
    std::fs::read_dir(dir)
        .map(|entries| entries.filter_map(|e| e.ok()).all(|e| e.file_name().to_str().is_some()))
        .unwrap_or(false)
}

Try / catch

match migrate_runtime(&target, &release_bin) {
    Ok(()) => {},
    Err(e) if e.to_string().contains("non-UTF-8 entry") =>
        eprintln!("remove/rename non-UTF-8 files in {}", release_bin.display()),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling migrate_runtime when the release runtime bin directory contains a file or directory whose name is not valid UTF-8 (raw bytes from an archive extraction or foreign filesystem).

Common situations: Extracting a release archive that contained byte-level filenames; files created by non-Unix tooling with legacy encodings; corruption during transfer.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/f9f92000df767dd8. Report an issue: GitHub.

Appendix: source

Thrown at crates/unicity-aos-bootstrap/src/migration.rs:710

    let metadata = fs::symlink_metadata(release_runtime_bin).map_err(|error| {
        if error.kind() == io::ErrorKind::NotFound {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                "bundled product release runtime executable set is not installed",
            )
        } else {
            error
        }
    })?;
    if metadata.file_type().is_symlink() || !metadata.is_dir() {
        return invalid("bundled product release runtime bin must be a real directory");
    }
    let expected: HashSet<_> = RUNTIME_EXECUTABLE_NAMES.iter().copied().collect();
    let mut actual = HashSet::new();
    for entry in fs::read_dir(release_runtime_bin)? {
        let entry = entry?;
        let name = entry.file_name().into_string().map_err(|_| {
            io::Error::new(
                io::ErrorKind::InvalidInput,
                "product release runtime bin contains a non-UTF-8 entry",
            )
        })?;
        let metadata = fs::symlink_metadata(entry.path())?;
        #[cfg(target_os = "macos")]
        if matches!(name.as_str(), "AstridFS.app" | "macos") {
            validate_packaged_filesystem_directory(&entry.path())?;
            continue;
        }
        if !expected.contains(name.as_str())
            || metadata.file_type().is_symlink()
            || !metadata.is_file()
            || !actual.insert(name)
        {
            return invalid("product release runtime contains unexpected data");
        }
    }

View on GitHub (pinned to f6f22024fb)