lyswhut/lx-music-desktop · error · Error

Unknown action: ${action}

Error message

Unknown action: ${action}

What it means

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.

Source

Thrown at src/renderer/core/useApp/useDeeplink/usePlayerAction.ts:32

      case 'skipNext':
        playNext()
        break
      case 'skipPrev':
        playPrev()
        break
      case 'togglePlay':
        togglePlay()
        break
      case 'collect':
        collectMusic()
        break
      case 'uncollect':
        uncollectMusic()
        break
      case 'dislike':
        dislikeMusic()
        break
      default: throw new Error('Unknown action: ' + (action as any ?? ''))
    }
  }
}

View on GitHub (pinned to 9c364b482e)

Solutions

  1. Confirm the action token matches one of the eight supported verbs.
  2. 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.
  3. Wrap the dispatcher in try-catch at the deeplink router and route failures to useDialog().
  4. Default missing/null action to a no-op or an explicit error before the switch.

Example fix

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

// after - typed action, clear message
type PlayerAction = 'play' | 'pause' | 'skipNext' | 'skipPrev' | 'togglePlay' | 'collect' | 'uncollect' | 'dislike'
// in the handler signature: (action: PlayerAction, ...)
      default: throw new Error(`Unknown player action: '${String(action ?? '')}'`)
Defensive patterns

Strategy: type-guard

Validate before calling

const PLAYER_ACTIONS = new Set(['play','pause','skipNext','skipPrev','togglePlay','collect','uncollect','dislike'])
if (!PLAYER_ACTIONS.has(action)) {
  showErrorDialog(`Unknown player action: ${action ?? ''}`)
  return
}

Type guard

type PlayerAction = 'play' | 'pause' | 'skipNext' | 'skipPrev' | 'togglePlay' | 'collect' | 'uncollect' | 'dislike'
const isPlayerAction = (a: unknown): a is PlayerAction =>
  typeof a === 'string' && ['play','pause','skipNext','skipPrev','togglePlay','collect','uncollect','dislike'].includes(a)

Try / catch

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

Prevention

When it happens

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

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

Related errors


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