{"record":{"id":"94fcfa1cda0ac772","repo":"cjpais/Handy","slug":"failed-to-init-hugging-face-api","errorCode":null,"errorMessage":"Failed to init Hugging Face API: {}","messagePattern":"Failed to init Hugging Face API: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/managers/model.rs","lineNumber":1932,"sourceCode":"            let stream_count = ATTEMPT_STREAMS[attempt - 1];\n            info!(\n                \"HF download attempt {}/{} for {} using {} concurrent stream(s)\",\n                attempt,\n                ATTEMPT_STREAMS.len(),\n                model_id,\n                stream_count\n            );\n\n            // Fresh client per attempt so a wedged connection from the previous\n            // try can't poison the retry.\n            let api = ApiBuilder::from_env()\n                // Ignore cached and environment-provided credentials. A stale token\n                // can make otherwise-public downloads fail authentication.\n                .with_token(None)\n                .with_progress(false)\n                .with_max_files(stream_count)\n                .build()\n                .map_err(|e| anyhow::anyhow!(\"Failed to init Hugging Face API: {}\", e))?;\n            let repo = api.repo(Repo::with_revision(\n                repo_id.clone(),\n                RepoType::Model,\n                revision.clone(),\n            ));\n            let progress = HfDownloadProgress::new(self.app_handle.clone(), model_id.clone());\n\n            // hf-hub has no internal timeouts, so a wedged connection would\n            // otherwise hang this attempt forever and neither the retry loop\n            // nor the mirror fallback would ever fire. The watchdog cancels a\n            // per-attempt child token when progress goes stale; a user cancel\n            // on the parent propagates through the same child.\n            let attempt_token = cancel_token.child_token();\n            let watchdog = tokio::spawn({\n                let probe = progress.clone();\n                let attempt_token = attempt_token.clone();\n                async move {\n                    loop {","sourceCodeStart":1914,"sourceCodeEnd":1950,"githubUrl":"https://github.com/cjpais/Handy/blob/98a4d80cce8ad41efec2a419b59d9e81229a35d7/src-tauri/src/managers/model.rs#L1914-L1950","documentation":"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)).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set HF_HOME to a writable directory with enough space for multi-GB models","Ensure HOME is set for whatever context launches the app (autostart .desktop, launchd, systemd)","Check disk space and write permissions on the cache root","If sandboxed, grant the app write access to its cache directory"],"exampleFix":"# before (service context, HOME stripped)\nExecStart=/usr/bin/handy --start-hidden\n\n# after\nEnvironment=HOME=/var/lib/handy\nEnvironment=HF_HOME=/var/lib/handy/.cache/huggingface\nExecStart=/usr/bin/handy --start-hidden","handlingStrategy":"validation","validationCode":"// pre-flight the hub cache dir before entering the download loop\nlet cache_root = std::env::var(\"HF_HOME\")\n    .map(PathBuf::from)\n    .unwrap_or_else(|_| {\n        let home = std::env::var(\"HOME\").expect(\"HOME must be set for hf-hub cache\");\n        PathBuf::from(home).join(\".cache/huggingface\")\n    });\nstd::fs::create_dir_all(&cache_root)\n    .map_err(|e| anyhow::anyhow!(\"hub cache {cache_root:?} not writable: {e}\"))?;","typeGuard":null,"tryCatchPattern":"let api = match ApiBuilder::from_env().with_token(None).build() {\n    Ok(a) => a,\n    Err(e) => anyhow::bail!(\"cannot init HF API — check HF_HOME/HOME and disk: {e}\"),\n};","preventionTips":["Set HF_HOME explicitly in managed launch contexts (services, autostart) to a writable dir","Ensure HOME is present in the environment that launches the app","Include cache-dir writability in startup diagnostics"],"tags":["rust","hf-hub","cache","environment","filesystem-permissions"],"backgroundTag":"cache-dir-not-writable","analyzedSha":"98a4d80cce8ad41efec2a419b59d9e81229a35d7","analyzedAt":"2026-08-16T20:58:09.966Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}