{"record":{"id":"130a8da4b0798544","repo":"rtk-ai/rtk","slug":"no-local-data-directory-available","errorCode":null,"errorMessage":"no local data directory available","messagePattern":"no local data directory available","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/core/retriever.rs","lineNumber":184,"sourceCode":"        .read_to_end(&mut out)\n        .context(\"gunzip\")?;\n    Ok(out)\n}\n\nfn db_path(cfg: &RetrieverConfig) -> Result<PathBuf> {\n    if let Ok(p) = std::env::var(\"RTK_RECALL_DB\") {\n        return Ok(PathBuf::from(p));\n    }\n    if let Some(ref p) = cfg.database_path {\n        return Ok(p.clone());\n    }\n    // A test that names no store must never reach the developer's own: its rows\n    // would ship as real usage through the telemetry ping.\n    #[cfg(test)]\n    let base = std::env::temp_dir().join(format!(\"rtk-test-store-{}\", std::process::id()));\n    #[cfg(not(test))]\n    let base = dirs::data_local_dir()\n        .ok_or_else(|| anyhow::anyhow!(\"no local data directory available\"))?\n        .join(super::constants::RTK_DATA_DIR);\n    Ok(base.join(RECALL_DB))\n}\n\nfn open(cfg: &RetrieverConfig) -> Result<Connection> {\n    let path = db_path(cfg)?;\n    if let Some(parent) = path.parent() {\n        let _ = crate::core::utils::create_private_dir(parent);\n    }\n    crate::core::utils::open_private(std::fs::OpenOptions::new().write(true).create(true), &path)\n        .with_context(|| format!(\"pre-create private recall DB: {}\", path.display()))?;\n    let conn = Connection::open(&path).with_context(|| format!(\"open {}\", path.display()))?;\n    // best-effort: NFS / read-only filesystems may reject WAL\n    let _ = conn.execute_batch(\"PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;\");\n    init_schema(&conn)?;\n    Ok(conn)\n}\n","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/rtk-ai/rtk/blob/0924356b4caba4989607227b7c8824d3d8098719/src/core/retriever.rs#L166-L202","documentation":"retriever::db_path builds the on-disk path of the recall SQLite database by starting from the platform's local data directory (dirs::data_local_dir()). On platforms where that directory cannot be determined, it returns this error instead of guessing a path.","triggerScenarios":"Calling open/open_existing/with_open when dirs::data_local_dir() returns None — typically when $XDG_DATA_HOME and $HOME are both unset, or on exotic environments (minimal containers, setuid contexts, some CI images) with no resolvable home directory.","commonSituations":"Running rtk in a Docker container without HOME set; stripped-down CI runners; cron/systemd services with an empty environment; Windows profiles without a LOCALAPPDATA equivalent.","solutions":["Set the HOME environment variable to a writable directory (e.g. export HOME=/root in containers).","Set XDG_DATA_HOME to an existing writable path so dirs can resolve the data dir.","Run rtk from an environment with a normal user profile rather than an empty env."],"exampleFix":"// before (Dockerfile)\nCMD [\"rtk\", \"gain\"]\n// after\nENV HOME=/root\nCMD [\"rtk\", \"gain\"]","handlingStrategy":"validation","validationCode":"import os, sys\nif not (os.environ.get('HOME') or os.environ.get('XDG_DATA_HOME')):\n    sys.exit('Set HOME or XDG_DATA_HOME before running rtk')","typeGuard":null,"tryCatchPattern":"match rtk_gain() {\n    Err(e) if e.to_string().contains(\"no local data directory\") => {\n        std::env::set_var(\"HOME\", \"/tmp\");\n        retry()\n    }\n    other => other,\n}","preventionTips":["Always set HOME in Docker/CI images","Set XDG_DATA_HOME explicitly in minimal environments","Avoid running rtk from services with an empty environment"],"tags":["filesystem","environment","database"],"backgroundTag":"missing-env-var","analyzedSha":"0924356b4caba4989607227b7c8824d3d8098719","analyzedAt":"2026-09-19T19:25:29.612Z","contentChangedAt":"2026-09-19T19:25:29.612Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}