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

  1. 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
  2. Remove any regular file occupying a needed directory component (ls -l on the path in the error)
  3. Free disk space or remount the volume read-write
  4. 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

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


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/d094c1ef68761443. Report an issue: GitHub.