{"record":{"id":"2027702d7a7b769b","repo":"lyswhut/lx-music-desktop","slug":"unknown-action-action","errorCode":null,"errorMessage":"Unknown action: ${action}","messagePattern":"Unknown action: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/core/useApp/useDeeplink/useMusicAction.js","lineNumber":236,"sourceCode":"\nexport default () => {\n  const handleSearchMusic = useSearchMusic()\n  const handlePlayMusic = usePlayMusic()\n  const handleSearchPlayMusic = useSearchPlayMusic()\n\n\n  return async(action, info) => {\n    switch (action) {\n      case 'search':\n        handleSearchMusic(info)\n        break\n      case 'play':\n        handlePlayMusic(info)\n        break\n      case 'searchPlay':\n        await handleSearchPlayMusic(info)\n        break\n      default: throw new Error('Unknown action: ' + action)\n    }\n  }\n}\n","sourceCodeStart":218,"sourceCodeEnd":240,"githubUrl":"https://github.com/lyswhut/lx-music-desktop/blob/9c364b482e5621a1d38b50e8610d2fb974457e6e/src/renderer/core/useApp/useDeeplink/useMusicAction.js#L218-L240","documentation":"Top-level music deep-link action dispatcher in useMusicAction.js. The switch at lines 226-236 accepts only 'search', 'play', and 'searchPlay'; any other action token reaches default at line 236 and throws 'Unknown action: <token>'. This is the entry point returned by the default export of the module.","triggerScenarios":"The deeplink router invokes the hook with an action string that is not search/play/searchPlay — e.g. 'queue', 'download', an empty string, or undefined. Happens when the URL scheme's action verb doesn't match this build's supported verbs.","commonSituations":"Protocol mismatch between the link sender and this receiver; a malformed link missing the action segment; a newer sender emitting an action this older build doesn't recognize.","solutions":["Verify the action token in the deep link matches one of search/play/searchPlay before dispatching.","If extending the protocol, add a case branch and keep the default as the safety net.","Catch at the deeplink router and surface unknown actions through useDialog() instead of an unhandled rejection.","Log the offending action so protocol drift is diagnosable."],"exampleFix":"// before\n      default: throw new Error('Unknown action: ' + action)\n\n// after - typed union + explicit message\nconst MUSIC_ACTIONS = new Set(['search', 'play', 'searchPlay'])\n// before dispatching:\nif (!MUSIC_ACTIONS.has(action)) {\n  throw new Error(`Unknown music action: '${action}'. Expected one of search, play, searchPlay`)\n}","handlingStrategy":"validation","validationCode":"const MUSIC_ACTIONS = new Set(['search', 'play', 'searchPlay'])\nif (!MUSIC_ACTIONS.has(action)) {\n  showErrorDialog(`Unknown music action: ${action}`)\n  return\n}","typeGuard":"const MUSIC_ACTIONS = ['search', 'play', 'searchPlay'] as const\ntype MusicAction = typeof MUSIC_ACTIONS[number]\nconst isMusicAction = (a) => typeof a === 'string' && (MUSIC_ACTIONS as readonly string[]).includes(a)","tryCatchPattern":"try {\n  await musicDispatcher(action, info)\n} catch (e) {\n  errorDialog(e.message)\n}","preventionTips":["Define the action set as a single constant imported by both the router and the dispatcher.","Treat an unknown action as a protocol-drift signal and log it.","Never let the dispatcher throw uncaught — always wrap at the router and show useDialog()."],"tags":["deeplink","validation","action-dispatch","switch-default"],"backgroundTag":null,"analyzedSha":"9c364b482e5621a1d38b50e8610d2fb974457e6e","analyzedAt":"2026-08-12T15:14:48.244Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}