{"record":{"id":"636f5480c1341231","repo":"GraphiteEditor/Graphite","slug":"failed-to-create-app-resource-dir","errorCode":null,"errorMessage":"failed to create app resource dir","messagePattern":"failed to create app resource dir","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"desktop/bundle/src/mac.rs","lineNumber":57,"sourceCode":"\tlet app_dir = out_dir.join(APP_NAME).with_extension(\"app\");\n\n\tclean_dir(&app_dir);\n\n\tcreate_app(&app_dir, APP_ID, APP_NAME, app_bin, false);\n\n\tfor helper_type in [None, Some(\"GPU\"), Some(\"Renderer\")] {\n\t\tlet helper_id_suffix = helper_type.map(|t| format!(\".{t}\")).unwrap_or_default();\n\t\tlet helper_id = format!(\"{APP_ID}.helper{helper_id_suffix}\");\n\t\tlet helper_name_suffix = helper_type.map(|t| format!(\" ({t})\")).unwrap_or_default();\n\t\tlet helper_name = format!(\"{APP_NAME} Helper{helper_name_suffix}\");\n\t\tlet helper_app_dir = app_dir.join(FRAMEWORKS_PATH).join(&helper_name).with_extension(\"app\");\n\t\tcreate_app(&helper_app_dir, &helper_id, &helper_name, helper_bin, true);\n\t}\n\n\tcopy_dir(&cef_path().join(CEF_FRAMEWORK), &app_dir.join(FRAMEWORKS_PATH).join(CEF_FRAMEWORK));\n\n\tlet resource_dir = app_dir.join(RESOURCES_PATH);\n\tfs::create_dir_all(&resource_dir).expect(\"failed to create app resource dir\");\n\n\tlet icon_file = workspace_path().join(\"branding/app-icons\").join(ICONS_FILE_NAME);\n\tfs::copy(icon_file, resource_dir.join(ICONS_FILE_NAME)).expect(\"failed to copy icon file\");\n\n\tapp_dir\n}\n\nfn create_app(app_dir: &Path, id: &str, name: &str, bin: &Path, is_helper: bool) {\n\tfs::create_dir_all(app_dir.join(EXEC_PATH)).unwrap();\n\n\tlet app_contents_dir: &Path = &app_dir.join(\"Contents\");\n\tcreate_info_plist(app_contents_dir, id, name, is_helper).unwrap();\n\tfs::copy(bin, app_dir.join(EXEC_PATH).join(name)).unwrap();\n}\n\nfn create_info_plist(dir: &Path, id: &str, exec_name: &str, is_helper: bool) -> Result<(), Box<dyn std::error::Error>> {\n\tlet info = InfoPlist {\n\t\tcf_bundle_name: exec_name.to_string(),","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/desktop/bundle/src/mac.rs#L39-L75","documentation":"Panic in Graphite's macOS .app bundler when fs::create_dir_all fails to create the Contents/Resources directory inside the generated Graphite.app bundle. create_dir_all walks every path component, so it fails if any component is an existing regular file, if the target volume/dir is read-only or lacks write permission, or if the disk is full. Because the tool uses .expect, any io::Error aborts bundle generation immediately.","triggerScenarios":"Running the desktop bundle binary for macOS when a previous interrupted run left a plain file where a directory is expected (e.g. a file named Resources under Contents), when the output directory is not writable by the current user, when the target volume is read-only, or when the disk is out of space.","commonSituations":"Building the bundle into a target/ or product directory owned by root or another user; a partially-created bundle from a crashed earlier run; running the bundler on a full disk or in a sandboxed/managed macOS environment that restricts writes to the build directory.","solutions":["Delete the partially-created Graphite.app output directory and re-run the bundler so it starts from a clean tree","Check write permission on the bundle output directory (chmod/chown) and that the volume is not read-only","Verify no regular file exists anywhere along the app_dir/Contents/Resources path (remove it or the stale bundle)","Confirm free disk space with df -h and free space if needed"],"exampleFix":"// before\nfs::create_dir_all(&resource_dir).expect(\"failed to create app resource dir\");\n\n// after\nfs::create_dir_all(&resource_dir).unwrap_or_else(|e| panic!(\"failed to create app resource dir at {}: {e}\", resource_dir.display()));","handlingStrategy":"validation","validationCode":"// Before bundling, ensure no regular file blocks the directory chain and the parent is writable\nfn can_create_resource_dir(app_dir: &Path) -> bool {\n\tlet resource_dir = app_dir.join(RESOURCES_PATH);\n\tlet mut cur = PathBuf::new();\n\tfor comp in resource_dir.components() {\n\t\tcur.push(comp);\n\t\tif cur.exists() && !cur.is_dir() {\n\t\t\treturn false; // a file occupies a directory slot\n\t\t}\n\t}\n\tlet probe = resource_dir.with_extension(\"probe\");\n\tstd::fs::create_dir_all(&resource_dir).is_ok() && std::fs::File::create(&probe).is_ok() && std::fs::remove_file(&probe).is_ok()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always start the bundler from a clean output directory (delete stale .app bundles first)","Run bundle generation with write access to the build directory and adequate free disk space","Replace .expect with unwrap_or_else so the panic message includes the failing path and io::Error"],"tags":["rust","macos","app-bundling","filesystem","build-tooling"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}