moeru-ai/airi · error · Error
Cannot close a DualSense controller while it is ${this.#life
Error message
Cannot close a DualSense controller while it is ${this.#lifecycle}. What it means
close() is only valid from the 'open' lifecycle state. The guard throws when close() is called while a transition is in progress ('opening' or 'closing'), i.e. another lifecycle operation still holds the device and closing now would race with it. Calling close() while already 'closed' returns silently and never reaches this error.
Source
Thrown at packages/input-playstation-dualsense-5/src/controller.ts:99
async close(): Promise<void> {
if (this.#lifecycle === 'closed')
return
if (this.#lifecycle !== 'open')
throw new Error(`Cannot close a DualSense controller while it is ${this.#lifecycle}.`)
this.#lifecycle = 'closing'
this.#device.removeEventListener('inputreport', this.#handleInputReport)
try {
if (this.#device.opened)
await this.#device.close()
}
finally {
this.#lifecycle = 'closed'
}
}View on GitHub (pinned to 9c213115f8)
Solutions
- Await the in-flight open()/close() promise before calling close() — the error message names the conflicting state.
- Serialize lifecycle calls behind a single promise chain or mutex in the owner of the controller.
- If close() was triggered by teardown (page unload, component unmount), guard against duplicate teardown paths sharing one controller.
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at packages/input-playstation-dualsense-5/src/controller.ts:99 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of moeru-ai/airi@9c213115f8 (2026-09-02).
Data as JSON: /api/errors/2a2cfd52325cea78.
Report an issue: GitHub.