GraphiteEditor/Graphite · error

failed to copy icon file

Error message

failed to copy icon file

What it means

Panic in the macOS bundler when fs::copy cannot copy the application icon (branding/app-icons/<ICONS_FILE_NAME>, an .icns file) into the freshly created Contents/Resources directory. fs::copy fails when the source icon file does not exist, when the source or destination path is unreadable/unwritable, or when the workspace root was resolved incorrectly so the source path points outside the repo.

Source

Thrown at desktop/bundle/src/mac.rs:60

	create_app(&app_dir, APP_ID, APP_NAME, app_bin, false);

	for helper_type in [None, Some("GPU"), Some("Renderer")] {
		let helper_id_suffix = helper_type.map(|t| format!(".{t}")).unwrap_or_default();
		let helper_id = format!("{APP_ID}.helper{helper_id_suffix}");
		let helper_name_suffix = helper_type.map(|t| format!(" ({t})")).unwrap_or_default();
		let helper_name = format!("{APP_NAME} Helper{helper_name_suffix}");
		let helper_app_dir = app_dir.join(FRAMEWORKS_PATH).join(&helper_name).with_extension("app");
		create_app(&helper_app_dir, &helper_id, &helper_name, helper_bin, true);
	}

	copy_dir(&cef_path().join(CEF_FRAMEWORK), &app_dir.join(FRAMEWORKS_PATH).join(CEF_FRAMEWORK));

	let resource_dir = app_dir.join(RESOURCES_PATH);
	fs::create_dir_all(&resource_dir).expect("failed to create app resource dir");

	let icon_file = workspace_path().join("branding/app-icons").join(ICONS_FILE_NAME);
	fs::copy(icon_file, resource_dir.join(ICONS_FILE_NAME)).expect("failed to copy icon file");

	app_dir
}

fn create_app(app_dir: &Path, id: &str, name: &str, bin: &Path, is_helper: bool) {
	fs::create_dir_all(app_dir.join(EXEC_PATH)).unwrap();

	let app_contents_dir: &Path = &app_dir.join("Contents");
	create_info_plist(app_contents_dir, id, name, is_helper).unwrap();
	fs::copy(bin, app_dir.join(EXEC_PATH).join(name)).unwrap();
}

fn create_info_plist(dir: &Path, id: &str, exec_name: &str, is_helper: bool) -> Result<(), Box<dyn std::error::Error>> {
	let info = InfoPlist {
		cf_bundle_name: exec_name.to_string(),
		cf_bundle_identifier: id.to_string(),
		cf_bundle_display_name: exec_name.to_string(),
		cf_bundle_executable: exec_name.to_string(),

View on GitHub (pinned to c507b35645)

Solutions

  1. Verify branding/app-icons/<ICONS_FILE_NAME> exists in the repo root and regenerate it via the branding workflow if missing
  2. Run the bundler through cargo from the workspace root so workspace_path() resolves correctly
  3. Check read permission on the icon file and write permission on the Resources directory
  4. Delete a stale or corrupted .app output and re-run the bundler

Example fix

// before
fs::copy(icon_file, resource_dir.join(ICONS_FILE_NAME)).expect("failed to copy icon file");

// after
fs::copy(&icon_file, resource_dir.join(ICONS_FILE_NAME)).unwrap_or_else(|e| panic!("failed to copy icon file from {}: {e}", icon_file.display()));
Defensive patterns

Strategy: validation

Validate before calling

// Before copying, assert the icon source exists and is readable
let icon_file = workspace_path().join("branding/app-icons").join(ICONS_FILE_NAME);
if !icon_file.is_file() {
	eprintln!("missing icon asset: {} (run the branding icon generation step)", icon_file.display());
	std::process::exit(1);
}

Prevention

When it happens

Trigger: The branding icon asset (branding/app-icons/<ICONS_FILE_NAME>) is missing from the checkout or was never generated; workspace_path() resolves to a wrong root because the bundler binary was run from outside the Cargo workspace; Resources became unwritable between creation and copy.

Common situations: Fresh clone or shallow checkout that lacks the generated icon artifact; skipping the branding/icon generation step; moving or running the compiled bundler binary from an absolute path that breaks the relative workspace resolution; read-only build directory.

Related errors


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/295a9752dd053730. Report an issue: GitHub.