aaif-goose/goose · warning
Download already in progress
Error message
Download already in progress
What it means
download_model_sharded refuses to start when an entry for model_id already has status Downloading, rejecting duplicate concurrent starts for the same model rather than deduplicating them. The companion reserve_download path exists so callers can do this check-and-insert atomically.
Source
Thrown at crates/goose-download-manager/src/lib.rs:229
pub async fn download_model_sharded_with_bearer_token(
&self,
model_id: String,
files: Vec<(String, PathBuf)>,
total_size_hint: u64,
bearer_token: Option<String>,
on_complete: Option<Box<dyn FnOnce() + Send + 'static>>,
) -> Result<()> {
info!(model_id = %model_id, file_count = files.len(), "Starting model download");
{
let mut downloads = self
.downloads
.lock()
.map_err(|_| anyhow::anyhow!("Failed to acquire lock"))?;
if let Some(existing) = downloads.get(&model_id) {
if existing.status == DownloadStatus::Downloading {
anyhow::bail!("Download already in progress");
}
if existing.status == DownloadStatus::Cancelled && !existing.task_exited {
anyhow::bail!(
"Download is being cancelled; wait for it to finish before restarting"
);
}
}
downloads.insert(
model_id.clone(),
DownloadProgress {
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,View on GitHub (pinned to 3810898a74)
Solutions
- Poll progress (get_progress / list_progress) and wait for the existing download instead of starting again
- Cancel the running download first if a restart is intended, then wait for task_exited
- Guard call sites so only one start per model_id is in flight
Example fix
// before
manager.download_model_sharded(model_id.clone(), files, size, token, None).await?;
// after
if manager.is_downloading(&model_id) {
// already running: poll list_progress() until it finishes
return Ok(());
}
manager.download_model_sharded(model_id.clone(), files, size, token, None).await?; Defensive patterns
Strategy: validation
Validate before calling
if manager.is_downloading(&model_id) {
// a download is already running; poll instead of starting a duplicate
poll_until_finished(&manager, &model_id).await;
} else {
manager.download_model_sharded(model_id.clone(), files, size, token, None).await?;
} Try / catch
if let Err(e) = manager.download_model_sharded(id, files, size, token, None).await {
if e.to_string() == "Download already in progress" {
poll_until_finished(&manager, &id).await;
return Ok(());
}
return Err(e);
} Prevention
- Debounce start actions in UIs so double-clicks cannot double-start
- Check is_downloading(model_id) before initiating a download
- In retry logic, distinguish 'already running' from 'failed' before restarting
When it happens
Trigger: Two concurrent download_model calls with the same model_id — double-triggered UI actions, retries that fire before the first attempt exits, parallel automation starting the same model.
Common situations: Front-ends firing start twice on double-click; retry logic that treats a slow start as failed and restarts immediately.
Related errors
- --concurrency must be at least 1
- Failed to acquire lock
- Download not found
- Download is being cancelled; wait for it to finish before re
- Unknown local inference backend '{}'
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/5110cabe5ef36a2b.
Report an issue: GitHub.