hcengineering/platform · error

Cannot resume from state: ${state}

Error message

Cannot resume from state: ${state}

What it means

`resume()` requires the recorder to be in exactly the 'paused' state. This error is thrown when resume is requested from 'idle', 'ready', 'recording', 'stopping', or 'stopped'. In particular, resuming a recorder that is already recording (not paused) is rejected — resume is not idempotent.

Source

Thrown at plugins/recorder-resources/src/stores/recorder.ts:185

      const { state } = get(store)
      if (state !== 'recording') {
        throw new Error(`Cannot pause from state: ${state}`)
      }

      if (screenRecorder === null) {
        throw new Error('No active recording')
      }

      await screenRecorder.pause()
      stopElapsedTimer()
      updateStore({ state: 'paused' })
    },

    async resume (): Promise<void> {
      const { state } = get(store)

      if (state !== 'paused') {
        throw new Error(`Cannot resume from state: ${state}`)
      }

      if (screenRecorder === null) {
        throw new Error('No active recording')
      }

      await screenRecorder.resume()
      startElapsedTimer()
      updateStore({ state: 'recording' })
    },

    async cancel (): Promise<void> {
      if (screenRecorder !== null) {
        await screenRecorder?.cancel()
        screenRecorder = null
      }

      const { result } = get(store)

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Only call `resume()` when the store state is 'paused'; if `state === 'recording'`, do nothing.
  2. Model the pause/resume control as a single toggle driven by the current state.
  3. Disable the resume control unless `state === 'paused'`.
  4. If the recording already ended, start a fresh session (`initialize` if needed, then `start()`) instead of resuming.

Example fix

// before
if (shouldContinue) void recorder.resume()

// after
const { state } = getStore(recorder)
if (state === 'paused' && shouldContinue) void recorder.resume()
Defensive patterns

Strategy: validation

Validate before calling

const { state } = get(recorder)
if (state === 'recording') return // already running, nothing to resume
if (state !== 'paused') return
await recorder.resume()

Type guard

function canResume(state: RecorderState): state is 'paused' {
  return state === 'paused'
}

Try / catch

try {
  await recorder.resume()
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Cannot resume from state:')) {
    // recording already running or finished; reconcile UI with store state
  } else throw err
}

Prevention

When it happens

Trigger: Calling `recorder.resume()` while `state === 'recording'` (already running); calling `resume()` before any recording started; calling `resume()` after `stop()` completed ('stopped'); calling `resume()` while a stop is pending ('stopping').

Common situations: A play/resume button that doesn't distinguish 'recording' from 'paused'; double-invocation of a resume handler; flows that resume after the stream-ended callback already stopped the recording; tests resuming without a prior pause.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/b9822064f89b8942. Report an issue: GitHub.