unicity-aos/aos-ce · error · io::Error
AOS capsule directory must be a real directory
Error message
AOS capsule directory must be a real directory: {} What it means
Thrown by validate_capsule_dir when the capsule path exists but is a symbolic link or not a directory. The library deliberately rejects symlinks so the capsule directory cannot be redirected elsewhere (an integrity/security measure), and requires a real directory to enumerate.
Solutions
- Replace the symlink with a real directory (e.g. copy or move the contents back, or bind-mount instead of symlink)
- Ensure the configured path is the actual directory, not a file or link
- If redirection is needed, change the configured path itself rather than symlinking
Example fix
// before ln -s /data/aos/capsules ~/.aos/capsules // after rm ~/.aos/capsules && mkdir ~/.aos/capsules && cp -a /data/aos/capsules/. ~/.aos/capsules/
Defensive patterns
Strategy: validation
Validate before calling
fn is_real_directory(path: &std::path::Path) -> bool {
match std::fs::symlink_metadata(path) {
Ok(md) => !md.file_type().is_symlink() && md.is_dir(),
Err(_) => false,
}
} Type guard
fn is_real_dir(md: &std::fs::Metadata) -> bool {
!md.file_type().is_symlink() && md.is_dir()
} Try / catch
match bootstrap::capsule_dir_with(&home) {
Err(e) if e.to_string().contains("must be a real directory") => {
eprintln!("Replace the symlink/file at the capsule path with a real directory");
}
Err(e) => return Err(e),
Ok(dir) => dir,
} Prevention
- Never symlink the capsule directory to another location; configure the real path instead
- Check symlink_metadata before pointing the library at a path
- Document that the capsule path must be a physical directory
When it happens
Trigger: Pointing capsule_dir_with at a symlink to the real directory; pointing it at a regular file or a mount point reported as non-dir; platform-specific filesystem entries where symlink_metadata reports a link.
Common situations: Users symlink ~/.aos/capsules to another disk to save space; environment variables or config pointing at a file instead of a directory; tmpfs/bind-mount setups where the path resolves oddly.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- product manifest path must be a regular file
- temporary product manifest path must be a regular file
- AOS capsule directory contains a non-regular entry
- AOS managed path must be a real directory
- AOS capsule directory is unavailable at
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/ba94efe0bf4d0c7a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/unicity-aos-bootstrap/src/lib.rs:725
));
}
assets.push(asset);
}
Ok(assets)
}
fn validate_capsule_dir(path: &Path, expected: &[String]) -> io::Result<PathBuf> {
let metadata = fs::symlink_metadata(path).map_err(|error| {
io::Error::new(
error.kind(),
format!(
"AOS capsule directory is unavailable at {}: {error}",
path.display()
),
)
})?;
if metadata.file_type().is_symlink() || !metadata.is_dir() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"AOS capsule directory must be a real directory: {}",
path.display()
),
));
}
let canonical = path.canonicalize()?;
let mut actual = Vec::new();
for entry in fs::read_dir(&canonical)? {
let entry = entry?;
let metadata = fs::symlink_metadata(entry.path())?;
if metadata.file_type().is_symlink() || !metadata.is_file() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!(
"AOS capsule directory contains a non-regular entry: {}",
entry.path().display()View on GitHub (pinned to f6f22024fb)