lyswhut/lx-music-desktop · error · Error

Unknown action: ${action}

Error message

Unknown action: ${action}

What it means

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.

Source

Thrown at src/renderer/core/useApp/useDeeplink/useMusicAction.js:236

export default () => {
  const handleSearchMusic = useSearchMusic()
  const handlePlayMusic = usePlayMusic()
  const handleSearchPlayMusic = useSearchPlayMusic()


  return async(action, info) => {
    switch (action) {
      case 'search':
        handleSearchMusic(info)
        break
      case 'play':
        handlePlayMusic(info)
        break
      case 'searchPlay':
        await handleSearchPlayMusic(info)
        break
      default: throw new Error('Unknown action: ' + action)
    }
  }
}

View on GitHub (pinned to 9c364b482e)

Solutions

  1. Verify the action token in the deep link matches one of search/play/searchPlay before dispatching.
  2. If extending the protocol, add a case branch and keep the default as the safety net.
  3. Catch at the deeplink router and surface unknown actions through useDialog() instead of an unhandled rejection.
  4. Log the offending action so protocol drift is diagnosable.

Example fix

// before
      default: throw new Error('Unknown action: ' + action)

// after - typed union + explicit message
const MUSIC_ACTIONS = new Set(['search', 'play', 'searchPlay'])
// before dispatching:
if (!MUSIC_ACTIONS.has(action)) {
  throw new Error(`Unknown music action: '${action}'. Expected one of search, play, searchPlay`)
}
Defensive patterns

Strategy: validation

Validate before calling

const MUSIC_ACTIONS = new Set(['search', 'play', 'searchPlay'])
if (!MUSIC_ACTIONS.has(action)) {
  showErrorDialog(`Unknown music action: ${action}`)
  return
}

Type guard

const MUSIC_ACTIONS = ['search', 'play', 'searchPlay'] as const
type MusicAction = typeof MUSIC_ACTIONS[number]
const isMusicAction = (a) => typeof a === 'string' && (MUSIC_ACTIONS as readonly string[]).includes(a)

Try / catch

try {
  await musicDispatcher(action, info)
} catch (e) {
  errorDialog(e.message)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of lyswhut/lx-music-desktop@9c364b482e (2026-08-12). Data as JSON: /api/errors/2027702d7a7b769b. Report an issue: GitHub.