{"record":{"id":"8132b41818d62922","repo":"tonhowtf/omniget","slug":"external-data-cache-failed-to-create","errorCode":null,"errorMessage":"external_data_cache: failed to create {}: {}","messagePattern":"external_data_cache: failed to create (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/src/plugin_host.rs","lineNumber":144,"sourceCode":"\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        })?;\n        Ok(dir)\n    }\n\n    fn get_cookie_file(&self, domain: &str, account: Option<&str>) -> Option<PathBuf> {\n        crate::cookies::account_path_for_consumer(domain, account)\n    }\n\n    fn cookie_status(&self, domain: &str) -> omniget_plugin_sdk::CookieStatus {\n        let registry = crate::cookies::load_registry();\n        let root = crate::cookies::root_domain_of(domain);\n        let bucket = match registry.buckets.get(&root) {\n            Some(b) => b,\n            None => return omniget_plugin_sdk::CookieStatus::Missing,","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/plugin_host.rs#L126-L162","documentation":"After resolving the base cache directory, external_data_cache builds base/external-cache/<plugin_id>/<namespace> and calls std::fs::create_dir_all. Any OS-level failure (permissions, read-only filesystem, name issues) is wrapped with the directory path and the io error text. The plugin then cannot store external data.","triggerScenarios":"create_dir_all fails because a parent directory is not writable, the disk is read-only/full, the path component derived from plugin_id/namespace is invalid on the filesystem, or an antivirus/ACL blocks creation.","commonSituations":"Read-only app dir in portable mode (app on a USB stick mounted read-only); Linux cache dir owned by another user after running once with sudo; Windows path length limits with long plugin ids/namespaces; disk full.","solutions":["Read the wrapped OS error: PermissionDenied → fix ownership of the cache base dir; ReadOnly/StorageFull → remount or free space.","Ensure the base cache directory is writable by the user running the app (chown/chmod on Linux, folder ACLs on Windows).","Sanitize/limit plugin_id and namespace length so the full path stays under filesystem limits.","In portable mode, move the app to a writable location."],"exampleFix":"// before (failing)\nstd::fs::create_dir_all(\"/home/otheruser/.cache/wtf.tonho.omniget/external-cache/myplugin/data\")\n// after\nsudo chown -R $USER ~/.cache/wtf.tonho.omniget\n# or in code: fall back to a writable dir on error","handlingStrategy":"try-catch","validationCode":"fn cache_base_writable(base: &std::path::Path) -> bool {\n    base.exists() || std::fs::create_dir_all(base).is_ok()\n}","typeGuard":null,"tryCatchPattern":"match host.external_data_cache(plugin_id, ns) {\n    Ok(dir) => store(dir),\n    Err(e) => {\n        log::error!(\"cache dir unavailable: {e}\"); // includes path + OS reason\n        // degrade: run plugin without external cache\n    }\n}","preventionTips":["Check the wrapped path and io::ErrorKind to fix ownership/permissions precisely","Never run the app as root once, which leaves root-owned cache dirs","Keep plugin_id/namespace short to avoid path-length limits","Ensure the install location (portable) is writable"],"tags":["filesystem","mkdir","permissions","plugin-host"],"backgroundTag":"mkdir-permission-denied","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"}