{"record":{"id":"b6f74c4fc7cd55a3","repo":"GraphiteEditor/Graphite","slug":"failed-to-get-data-directory","errorCode":null,"errorMessage":"Failed to get data directory","messagePattern":"Failed to get data directory","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"desktop/src/dirs.rs","lineNumber":32,"sourceCode":"\t\ttracing::error!(\"Failed to read directory at {path:?}\");\n\t\treturn;\n\t};\n\tfor entry in entries.flatten() {\n\t\tlet entry_path = entry.path();\n\t\tif entry_path.is_dir() {\n\t\t\tif let Err(e) = fs::remove_dir_all(&entry_path) {\n\t\t\t\ttracing::error!(\"Failed to remove directory at {:?}: {}\", entry_path, e);\n\t\t\t}\n\t\t} else if entry_path.is_file() {\n\t\t\tif let Err(e) = fs::remove_file(&entry_path) {\n\t\t\t\ttracing::error!(\"Failed to remove file at {:?}: {}\", entry_path, e);\n\t\t\t}\n\t\t}\n\t}\n}\n\npub(crate) fn app_data_dir() -> PathBuf {\n\tlet path = dirs::data_dir().expect(\"Failed to get data directory\").join(APP_DIRECTORY_NAME);\n\tensure_dir_exists(&path);\n\tpath\n}\n\npub(crate) fn app_autosave_documents_dir() -> PathBuf {\n\tlet path = app_data_dir().join(APP_DOCUMENTS_DIRECTORY_NAME);\n\tensure_dir_exists(&path);\n\tpath\n}\n\npub(crate) fn app_resources_dir() -> PathBuf {\n\tlet path = app_data_dir().join(APP_RESOURCES_DIRECTORY_NAME);\n\tensure_dir_exists(&path);\n\tpath\n}\n\n// TODO: Eventually remove this cleanup code for the old \"browser\" CEF directory\npub(crate) fn delete_old_cef_browser_directory() {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/desktop/src/dirs.rs#L14-L50","documentation":"Panic when dirs::data_dir() returns None. The dirs crate returns an Option: on Linux it is None when neither XDG_DATA_HOME nor a usable HOME is set (empty or unset); on Windows it wraps the Known Folder API which can fail in stripped-down environments; on macOS it is None when the home directory cannot be determined. The desktop app then cannot locate its data directory and aborts.","triggerScenarios":"Launching Graphite with HOME unset or empty (systemd service, cron job, minimal Docker container); XDG_DATA_HOME set to an empty string; a Windows session where SHGetKnownFolderPath fails; env vars stripped by a test harness or launcher.","commonSituations":"Running the desktop app from a daemon/service context or CI container that does not inherit a user environment; docker run without a HOME or with env cleared; SSH sessions with unusual PAM configurations.","solutions":["Set a valid HOME (or XDG_DATA_HOME) in the process environment: docker -e HOME=/home/user or Environment=HOME=... in the service unit","Verify with env | grep -E 'HOME|XDG_DATA_HOME' from the same launcher context","Fix the launcher/shell profile that strips environment variables","For tests, provide an explicit temp dir as the data dir instead of relying on the ambient environment"],"exampleFix":"// before\nlet path = dirs::data_dir().expect(\"Failed to get data directory\").join(APP_DIRECTORY_NAME);\n\n// after\nlet base = dirs::data_dir().or_else(|| std::env::var(\"HOME\").ok().map(PathBuf::from).map(|h| h.join(\".local/share\")))\n\t.unwrap_or_else(|| panic!(\"Failed to get data directory: set HOME or XDG_DATA_HOME\"));\nlet path = base.join(APP_DIRECTORY_NAME);","handlingStrategy":"validation","validationCode":"// Check the environment before any dirs::data_dir() call\nfn data_base_dir() -> Option<PathBuf> {\n\tif cfg!(target_os = \"linux\") && std::env::var_os(\"XDG_DATA_HOME\").is_none() && std::env::var_os(\"HOME\").is_none() {\n\t\treturn None;\n\t}\n\tdirs::data_dir()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Launch the app from a normal login shell or set HOME explicitly in service/container units","For headless/CI runs, set XDG_DATA_HOME to a writable temp directory","Handle the None case with an actionable message naming the missing environment variable"],"tags":["rust","dirs-crate","environment","home-directory","app-initialization"],"backgroundTag":"missing-home-env-var","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}