Skip to content

Troubleshooting

Use this guide when playback behavior is failing in a real app and you need the next correct check, not a full API explanation.

  1. Capture the exact error.code from playback-error when available.
  2. Verify initialization order (audioPlayer.setup() and mediaSession.setup() as needed).
  3. Verify queue and active-track preconditions (add(...), startIndex, getSnapshot()).
  4. Verify runtime capabilities before sending optional commands (getCapabilities()).
  5. If symptoms look native-environment-specific, run legato native doctor.

Use error.code as the machine-stable branch key.

error.codeMost likely categoryNext action
player_not_setupInitialization orderEnsure await audioPlayer.setup() ran before playback commands. See Set Up Legato Capacitor.
empty_queueQueue preconditionsVerify add({ tracks: [...] }) succeeds before play(). Then inspect getSnapshot().queue.
invalid_indexQueue addressingValidate skipTo({ index }), remove({ index }), or startIndex against current queue length.
no_active_trackActive-track selectionRe-check startIndex and currentIndex in snapshot after queue insertion.
unsupported_operationCapability projectionGate UI/action on getCapabilities().supported. See Capabilities.
seek_failedSeek runtime pathConfirm seek capability is currently supported before calling seekTo.
invalid_urlTrack input validityRe-check Track.url value and transport-level accessibility in your environment.
load_failedMedia loadingRe-check media URL reachability and track metadata assumptions; inspect error.details for adapter context.
playback_failedRuntime playbackObserve state transitions and error payload together (playback-state-changed + playback-error).
platform_errorNative/platform layerCollect error.details, then run legato native doctor for supported native checks.

Symptom: play() does nothing or fails immediately

Section titled “Symptom: play() does nothing or fails immediately”
  1. Run await audioPlayer.getSnapshot() and confirm queue is not empty.
  2. Confirm setup already completed in this app lifecycle (await audioPlayer.setup()).
  3. Confirm an active track exists (currentIndex !== null, currentTrack !== null).
  4. Register onPlaybackError and branch by error.code.

Symptom: seek controls are visible but seek fails

Section titled “Symptom: seek controls are visible but seek fails”
  1. Read capabilities right before rendering/handling seek:
const caps = await audioPlayer.getCapabilities();
const canSeek = caps.supported.includes('seek');
  1. Hide or disable seek controls when canSeek is false.
  2. If canSeek is true but seek_failed occurs, log error.details and runtime state snapshot for diagnosis.

Symptom: remote controls do not trigger app actions

Section titled “Symptom: remote controls do not trigger app actions”
  1. Confirm await mediaSession.setup() is called (separate from audioPlayer.setup()).
  2. Confirm listeners are registered and retained (not garbage-collected by component teardown).
  3. Confirm you are testing on a device/context that emits media-session controls.
  4. For seek-specific remote controls, confirm seek capability is currently projected.

Symptom: local UI state drifts from actual playback state

Section titled “Symptom: local UI state drifts from actual playback state”
  1. Prefer a sync controller (createLegatoSync or createAudioPlayerSync) for local projection.
  2. Ensure sync.start() is called once and sync.stop() runs on teardown.
  3. On foreground resume, run await sync.resync() before trusting stale UI state.

Symptom: native integration behaves differently than expected

Section titled “Symptom: native integration behaves differently than expected”
  1. Run legato native doctor from repository context supported by the CLI.
  2. If you need a preview of safe changes, run legato native configure --dry-run.
  3. Apply changes intentionally with legato native configure --apply and re-run doctor.
import {
audioPlayer,
mediaSession,
onPlaybackError,
onPlaybackStateChanged,
} from '@ddgutierrezc/legato-capacitor';
await audioPlayer.setup();
await mediaSession.setup();
onPlaybackStateChanged(({ state }) => console.log('[state]', state));
onPlaybackError(({ error }) => {
console.error('[legato:error]', error.code, error.message, error.details);
});
console.log('[snapshot]', await audioPlayer.getSnapshot());
console.log('[capabilities]', await audioPlayer.getCapabilities());