Skip to content

FSMError

The error type thrown by AFSM, extending Error.

Definition

export class FSMError extends Error {
state: State // state at the time of error
message: string
cause?: Error // original error (if any)
constructor(state: State, message: string, cause?: Error)
}

Fields

FieldDescription
stateThe FSM’s state when the error occurred (usually oldState, since state rolls back)
messageError message
causeOriginal error. When the method throws, the original Error is wrapped as cause

When thrown

State validation failure

@ChangeState’s from doesn’t match:

@ChangeState('idle', 'done')
async fetch() {}
await obj.fetch() // not in idle
// FSMError: MyFSM fetch to done failed: current state [*] not from idle
// err.state === '[*]'

Method execution failure

When the original method throws, it’s wrapped in FSMError:

@ChangeState('idle', 'done')
async fetch() {
throw new Error('network')
}
try { await obj.fetch() } catch (e) {
if (e instanceof FSMError) {
e.cause // Error: network
e.state // 'idle' (rolled back)
}
}

State guard failure

@Includes / @Excludes not satisfied:

@Includes('playing')
pause() {} // not in playing
// FSMError: Player pause failed: current state [*] not in playing

Checking FSMError

import { FSMError } from 'afsm'
try {
await obj.fetch()
} catch (e) {
if (e instanceof FSMError) {
// it's an AFSM-thrown error
}
}

ignoreError behavior

With opt.ignoreError: true, the error is not rejected/thrown — it’s returned as the value:

  • Async mode: return Promise.resolve(err)
  • Sync mode: return err
@ChangeState('idle', 'done', { ignoreError: true })
async fetch() {
throw new Error('x')
}
const r = await obj.fetch()
r instanceof FSMError // true

See also