{"record":{"id":"89ca3c9d3ac29754","repo":"lyswhut/lx-music-desktop","slug":"unknown-action-action-89ca3c","errorCode":null,"errorMessage":"Unknown action: ${action}","messagePattern":"Unknown action: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/core/useApp/useDeeplink/usePlayerAction.ts","lineNumber":32,"sourceCode":"      case 'skipNext':\n        playNext()\n        break\n      case 'skipPrev':\n        playPrev()\n        break\n      case 'togglePlay':\n        togglePlay()\n        break\n      case 'collect':\n        collectMusic()\n        break\n      case 'uncollect':\n        uncollectMusic()\n        break\n      case 'dislike':\n        dislikeMusic()\n        break\n      default: throw new Error('Unknown action: ' + (action as any ?? ''))\n    }\n  }\n}\n","sourceCodeStart":14,"sourceCodeEnd":36,"githubUrl":"https://github.com/lyswhut/lx-music-desktop/blob/9c364b482e5621a1d38b50e8610d2fb974457e6e/src/renderer/core/useApp/useDeeplink/usePlayerAction.ts#L14-L36","documentation":"Player deep-link action dispatcher in usePlayerAction.ts:32. The switch handles play/pause/skipNext/skipPrev/togglePlay/collect/uncollect/dislike; the default branch throws 'Unknown action: <action>'. The `(action as any ?? '')` cast signals the input is loosely typed at this boundary, so a nullish action becomes 'Unknown action: ' with an empty tail.","triggerScenarios":"A player deep link whose action is not in the supported set, or whose action field is null/undefined (yielding the empty-suffix variant), reaches the switch default at usePlayerAction.ts:32.","commonSituations":"A newer sender emits an action this build doesn't recognize; the URL template omits the action segment so it arrives undefined; an integration typo like 'playNext' instead of 'skipNext'.","solutions":["Confirm the action token matches one of the eight supported verbs.","Tighten the parameter type from `any` to a string-literal union so invalid values are caught at compile time instead of leaking to the switch.","Wrap the dispatcher in try-catch at the deeplink router and route failures to useDialog().","Default missing/null action to a no-op or an explicit error before the switch."],"exampleFix":"// before\n      default: throw new Error('Unknown action: ' + (action as any ?? ''))\n\n// after - typed action, clear message\ntype PlayerAction = 'play' | 'pause' | 'skipNext' | 'skipPrev' | 'togglePlay' | 'collect' | 'uncollect' | 'dislike'\n// in the handler signature: (action: PlayerAction, ...)\n      default: throw new Error(`Unknown player action: '${String(action ?? '')}'`)","handlingStrategy":"type-guard","validationCode":"const PLAYER_ACTIONS = new Set(['play','pause','skipNext','skipPrev','togglePlay','collect','uncollect','dislike'])\nif (!PLAYER_ACTIONS.has(action)) {\n  showErrorDialog(`Unknown player action: ${action ?? ''}`)\n  return\n}","typeGuard":"type PlayerAction = 'play' | 'pause' | 'skipNext' | 'skipPrev' | 'togglePlay' | 'collect' | 'uncollect' | 'dislike'\nconst isPlayerAction = (a: unknown): a is PlayerAction =>\n  typeof a === 'string' && ['play','pause','skipNext','skipPrev','togglePlay','collect','uncollect','dislike'].includes(a)","tryCatchPattern":"try {\n  playerDispatcher(action, info)\n} catch (e) {\n  errorDialog(e.message)\n}","preventionTips":["Type the action parameter as a string-literal union, not `any`, so invalid values fail at compile time.","Guard against nullish action before the switch to avoid the empty-suffix 'Unknown action: ' variant.","Keep the action set in one shared constant referenced by router and dispatcher."],"tags":["deeplink","validation","player","typescript","action-dispatch"],"backgroundTag":null,"analyzedSha":"9c364b482e5621a1d38b50e8610d2fb974457e6e","analyzedAt":"2026-08-12T15:14:48.244Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}