cjpais/Handy · error

Failed to init Hugging Face API: {}

Error message

Failed to init Hugging Face API: {}

What it means

hf-hub's ApiBuilder::from_env()...build() failed inside the per-attempt download loop. build() resolves and prepares the hub cache directory (HF_HOME or ~/.cache/huggingface) and returns Err when that directory cannot be created or written. Token and endpoint config from the environment are otherwise permissive (the code explicitly passes with_token(None)).

Source

Thrown at src-tauri/src/managers/model.rs:1932

            let stream_count = ATTEMPT_STREAMS[attempt - 1];
            info!(
                "HF download attempt {}/{} for {} using {} concurrent stream(s)",
                attempt,
                ATTEMPT_STREAMS.len(),
                model_id,
                stream_count
            );

            // Fresh client per attempt so a wedged connection from the previous
            // try can't poison the retry.
            let api = ApiBuilder::from_env()
                // Ignore cached and environment-provided credentials. A stale token
                // can make otherwise-public downloads fail authentication.
                .with_token(None)
                .with_progress(false)
                .with_max_files(stream_count)
                .build()
                .map_err(|e| anyhow::anyhow!("Failed to init Hugging Face API: {}", e))?;
            let repo = api.repo(Repo::with_revision(
                repo_id.clone(),
                RepoType::Model,
                revision.clone(),
            ));
            let progress = HfDownloadProgress::new(self.app_handle.clone(), model_id.clone());

            // hf-hub has no internal timeouts, so a wedged connection would
            // otherwise hang this attempt forever and neither the retry loop
            // nor the mirror fallback would ever fire. The watchdog cancels a
            // per-attempt child token when progress goes stale; a user cancel
            // on the parent propagates through the same child.
            let attempt_token = cancel_token.child_token();
            let watchdog = tokio::spawn({
                let probe = progress.clone();
                let attempt_token = attempt_token.clone();
                async move {
                    loop {

View on GitHub (pinned to 98a4d80cce)

Solutions

  1. Set HF_HOME to a writable directory with enough space for multi-GB models
  2. Ensure HOME is set for whatever context launches the app (autostart .desktop, launchd, systemd)
  3. Check disk space and write permissions on the cache root
  4. If sandboxed, grant the app write access to its cache directory

Example fix

# before (service context, HOME stripped)
ExecStart=/usr/bin/handy --start-hidden

# after
Environment=HOME=/var/lib/handy
Environment=HF_HOME=/var/lib/handy/.cache/huggingface
ExecStart=/usr/bin/handy --start-hidden
Defensive patterns

Strategy: validation

Validate before calling

// pre-flight the hub cache dir before entering the download loop
let cache_root = std::env::var("HF_HOME")
    .map(PathBuf::from)
    .unwrap_or_else(|_| {
        let home = std::env::var("HOME").expect("HOME must be set for hf-hub cache");
        PathBuf::from(home).join(".cache/huggingface")
    });
std::fs::create_dir_all(&cache_root)
    .map_err(|e| anyhow::anyhow!("hub cache {cache_root:?} not writable: {e}"))?;

Try / catch

let api = match ApiBuilder::from_env().with_token(None).build() {
    Ok(a) => a,
    Err(e) => anyhow::bail!("cannot init HF API — check HF_HOME/HOME and disk: {e}"),
};

Prevention

When it happens

Trigger: HOME unset (running as a service/daemon without a login environment); HF_HOME pointing at an unwritable or nonexistent-parent path; read-only home directory; disk full; sandboxed app whose filesystem permission excludes the cache path.

Common situations: Autostart entries and window-manager launchers that strip environment variables; snap/flatpak confinement; CI runners with a read-only home; small temp disks where ~/.cache resides.

Related errors


AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16). Data as JSON: /api/errors/94fcfa1cda0ac772. Report an issue: GitHub.