{"record":{"id":"441904742336846b","repo":"tonhowtf/omniget","slug":"external-data-cache-app-data-dir-unavailable","errorCode":null,"errorMessage":"external_data_cache: app data dir unavailable","messagePattern":"external_data_cache: app data dir unavailable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/plugin_host.rs","lineNumber":131,"sourceCode":"    fn external_data_cache(&self, plugin_id: &str, namespace: &str) -> anyhow::Result<PathBuf> {\n        if plugin_id.is_empty() {\n            anyhow::bail!(\"external_data_cache: plugin_id must not be empty\");\n        }\n        if namespace.is_empty() {\n            anyhow::bail!(\"external_data_cache: namespace must not be empty\");\n        }\n        if plugin_id.contains(['/', '\\\\', ':', '\\0']) || namespace.contains(['/', '\\\\', ':', '\\0'])\n        {\n            anyhow::bail!(\n                \"external_data_cache: plugin_id/namespace must not contain path separators or null bytes\"\n            );\n        }\n\n        // portable installs keep every file next to the app, so the cache\n        // lives under the app data dir instead of the OS cache dir\n        let base = if std::env::var(\"OMNIGET_PORTABLE\").is_ok() {\n            omniget_core::core::paths::app_data_dir()\n                .ok_or_else(|| anyhow::anyhow!(\"external_data_cache: app data dir unavailable\"))?\n                .join(\"cache\")\n        } else {\n            dirs::cache_dir()\n                .ok_or_else(|| {\n                    anyhow::anyhow!(\n                        \"external_data_cache: OS cache dir unavailable on this platform\"\n                    )\n                })?\n                .join(\"wtf.tonho.omniget\")\n        };\n        let dir = base.join(\"external-cache\").join(plugin_id).join(namespace);\n        std::fs::create_dir_all(&dir).map_err(|e| {\n            anyhow::anyhow!(\n                \"external_data_cache: failed to create {}: {}\",\n                dir.display(),\n                e\n            )\n        })?;","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/plugin_host.rs#L113-L149","documentation":"external_data_cache resolves the base directory for a plugin's external cache. In portable mode (OMNIGET_PORTABLE env var set) it uses omniget_core::core::paths::app_data_dir(); when that returns None it raises this error. It means the portable install's app data directory could not be determined, so no cache directory can be created.","triggerScenarios":"Calling external_data_cache with OMNIGET_PORTABLE set while paths::app_data_dir() returns None — typically when the executable path cannot be resolved or the computed app dir fails platform constraints (e.g. running from a weird location, permission on the exe path).","commonSituations":"Portable build run from a read-only mount or temp dir where the exe path resolution fails; exotic launch context (systemd service, container) without the expected env; regression in the paths helper on a platform update.","solutions":["Check that OMNIGET_PORTABLE is intentionally set; unset it to use the normal OS cache dir path.","Ensure the executable lives in a writable, resolvable location so app_data_dir() can compute the dir.","Pass a fallback base dir explicitly to the cache helper.","If persistent, file a bug with paths::app_data_dir including OS and launch context."],"exampleFix":"// before\nlet base = paths::app_data_dir().ok_or_else(|| anyhow!(\"external_data_cache: app data dir unavailable\"))?.join(\"cache\");\n// after (caller fallback)\nmatch plugin_host.external_data_cache(plugin_id, ns) {\n    Ok(dir) => dir,\n    Err(e) => { log::warn!(\"cache unavailable: {e}\"); std::env::temp_dir().join(\"omniget-cache\") }\n}","handlingStrategy":"fallback","validationCode":"let portable = std::env::var(\"OMNIGET_PORTABLE\").is_ok();\nif portable && omniget_core::core::paths::app_data_dir().is_none() {\n    eprintln!(\"portable mode cannot resolve app data dir; unset OMNIGET_PORTABLE or run from a writable location\");\n}","typeGuard":null,"tryCatchPattern":"let dir = match host.external_data_cache(pid, ns) {\n    Ok(d) => d,\n    Err(e) => { log::warn!(\"cache fallback: {e}\"); std::env::temp_dir().join(\"omniget-external-cache\") }\n};","preventionTips":["Ship portable builds only launched from writable locations","Fall back to a temp/user dir when app data resolution fails","Document OMNIGET_PORTABLE's requirement for a resolvable exe path"],"tags":["portable-mode","cache-directory","plugin-host","paths"],"backgroundTag":"missing-env-var","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}