{"record":{"id":"a0be6b725a756376","repo":"mihomo-party-org/clash-party","slug":"osascript-exited-res-status","errorCode":null,"errorMessage":"osascript exited ${res.status}","messagePattern":"osascript exited (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/utils/appName.ts","lineNumber":60,"sourceCode":"\nfunction getLocalizedAppName(appPath: string): string {\n  const escapedPath = appPath.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")\n  const jxa = `\n  ObjC.import('Foundation');\n  const fm = $.NSFileManager.defaultManager;\n  const name = fm.displayNameAtPath('${escapedPath}');\n  name.js;\n`\n  const res = spawnSync('osascript', ['-l', 'JavaScript'], {\n    input: jxa,\n    encoding: 'utf8',\n    stdio: ['pipe', 'pipe', 'pipe']\n  })\n  if (res.error) {\n    throw res.error\n  }\n  if (res.status !== 0) {\n    throw new Error(res.stderr.trim() || `osascript exited ${res.status}`)\n  }\n  return res.stdout.trim()\n}\n","sourceCodeStart":42,"sourceCodeEnd":64,"githubUrl":"https://github.com/mihomo-party-org/clash-party/blob/911e090537acdf7c50bee1c3aebecc2ef119a8b5/src/main/utils/appName.ts#L42-L64","documentation":"getLocalizedAppName shells out to macOS `osascript` (AppleScript via Sp.spawnSync-style exec) to ask the system for a localized app name. If the script process exits with a non-zero status and stderr is empty, this generic fallback 'osascript exited <status>' is thrown. It means the AppleScript run itself failed (syntax, sandboxing, or the target app not found), not a spawn failure (that would throw res.error instead).","triggerScenarios":"Calling appName -> getLocalizedAppName on macOS where osascript returns status != 0 with empty stderr — e.g. the AppleScript references an app path that no longer exists, or Automation/TCC permission denies the query and stderr is swallowed.","commonSituations":"App renamed/removed between listing and lookup; running in an environment where osascript is blocked (CI, hardened runtime without Apple Events entitlement); macOS update changes scripting interface; running as root without a GUI session.","solutions":["Run the same osascript command manually in Terminal with the same app path to see the real failure and reproduce it.","Grant Automation/AppleEvents permission for the app in System Settings > Privacy & Security > Automation (or add the AppleEvents entitlement).","Validate the app path exists before querying and skip/short-circuit missing apps.","Fall back to the raw bundle name from the .app directory instead of the localized name when osascript fails.","Reinstall/relocate the target application if its bundle is broken or was moved."],"exampleFix":"// before\nconst name = getLocalizedAppName('/Applications/OldName.app')\n// after: guard existence and degrade gracefully\nimport { existsSync } from 'fs'\nconst path = '/Applications/OldName.app'\nlet name = basename(path, '.app')\nif (existsSync(join(path, 'Contents', 'Info.plist'))) {\n  try {\n    name = getLocalizedAppName(path)\n  } catch {\n    /* keep bundle-name fallback */\n  }\n}","handlingStrategy":"fallback","validationCode":"import { existsSync } from 'fs'\n// check the app bundle exists before asking osascript about it\nconst appPath = '/Applications/SomeApp.app'\nif (!existsSync(appPath)) {\n  throw new Error(`App bundle missing: ${appPath}`)\n}","typeGuard":null,"tryCatchPattern":"let name: string\ntry {\n  name = getLocalizedAppName(appPath)\n} catch {\n  // fall back to the bundle directory name\n  name = basename(appPath, '.app')\n}","preventionTips":["Always keep a non-osascript fallback (bundle name from Info.plist) for app display names","Check Automation/AppleEvents permissions during onboarding on macOS","Validate app paths exist before querying","Test on CI/headless environments where AppleScript may be unavailable"],"tags":["macos","osascript","subprocess","apple-events"],"backgroundTag":"osascript-nonzero-exit","analyzedSha":"911e090537acdf7c50bee1c3aebecc2ef119a8b5","analyzedAt":"2026-08-30T13:00:49.174Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}