aaif-goose/goose · error
Failed to create directory: {}
Error message
Failed to create directory: {} What it means
Raised in download_model_sharded_with_bearer_token while preparing the transfer: tokio::fs::create_dir_all on the parent directory of one of the destination paths returned an io::Error, which is appended to the message. No HTTP request is made and the spawned task never runs, so the progress entry inserted just before remains status Downloading with task_exited false until the process restarts.
Source
Thrown at crates/goose-download-manager/src/lib.rs:259
model_id: model_id.clone(),
status: DownloadStatus::Downloading,
bytes_downloaded: 0,
total_bytes: total_size_hint,
progress_percent: 0.0,
speed_bps: None,
eta_seconds: None,
error: None,
task_exited: false,
},
);
}
// Create parent directories for all files
for (_, dest) in &files {
if let Some(parent) = dest.parent() {
tokio::fs::create_dir_all(parent)
.await
.map_err(|e| anyhow::anyhow!("Failed to create directory: {}", e))?;
}
}
let downloads = self.downloads.clone();
let model_id_clone = model_id.clone();
let files_for_cleanup: Vec<PathBuf> = files.iter().map(|(_, d)| d.clone()).collect();
tokio::spawn(async move {
let result = Self::download_files_sequentially(
&files,
&downloads,
&model_id_clone,
bearer_token.as_deref(),
)
.await;
match result {
Ok(_) => {View on GitHub (pinned to 3810898a74)
Solutions
- Check the exact parent path in the error message: fix ownership/permissions or move the destination under a writable directory such as the goose data dir
- Remove any regular file occupying a needed directory component (ls -l on the path in the error)
- Free disk space or remount the volume read-write
- Verify the path with a manual mkdir -p before rerunning
Example fix
// before
manager.download_model_sharded(id, files, hint, None).await?;
// after: fail with a precise, actionable path before the download starts
for (_, dest) in &files {
if let Some(parent) = dest.parent() {
std::fs::create_dir_all(parent)
.map_err(|e| anyhow::anyhow!("unwritable download dir {}: {e}", parent.display()))?;
}
}
manager.download_model_sharded(id, files, hint, None).await?; Defensive patterns
Strategy: validation
Validate before calling
// prove the destination tree is creatable/writable before starting
for (_, dest) in &files {
let parent = dest.parent().context("destination must have a parent")?;
std::fs::create_dir_all(parent)
.with_context(|| format!("cannot create download dir {}", parent.display()))?;
} Try / catch
match err.downcast_ref::<std::io::Error>() {
Some(io) if io.kind() == std::io::ErrorKind::PermissionDenied => surface("pick a writable folder"),
Some(io) if io.kind() == std::io::ErrorKind::NotADirectory => surface("a file occupies the path"),
_ => surface(err),
} Prevention
- Root destinations under the application data dir, not system paths
- Run a mkdir -p smoke test in setup/CI on the download root
- Treat EACCES/ENOTDIR/EROFS as configuration errors, not transient ones - do not retry
When it happens
Trigger: A destination path whose parent is unwritable (EACCES), sits on a read-only volume, has a regular file where a directory component is needed (ENOTDIR), exceeds name length limits, or the disk is full; also symlink loops or NFS mounts denying creation.
Common situations: Download destination rooted outside the goose data dir (e.g. /usr/share or a mounted volume) without write permission; a previous run left a file named like a directory component; sandboxed environments (containers, macOS app containers) restricting writes.
Related errors
- Failed to list recipes: {}
- Download is being cancelled; wait for it to finish before re
- Download cancelled
- Download failed after {} retries: {}
- Failed to download: HTTP {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/d094c1ef68761443.
Report an issue: GitHub.