{"record":{"id":"13e49a3037b2aec9","repo":"tinyhumansai/openhuman","slug":"ptt-cancel-failed-during-preempt","errorCode":null,"errorMessage":"[ptt] cancel failed during preempt","messagePattern":"\\[ptt\\] cancel failed during preempt","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/pttService.ts","lineNumber":185,"sourceCode":"      threadId,\n      heldMs: deps.now() - session.startedAtMs,\n      finalizedByWatchdog: fromWatchdog,\n      transcriptLen: trimmed.length,\n    });\n  };\n\n  return {\n    async onStart(sessionId) {\n      // Preempt: if another session is active, cancel it.\n      if (active) {\n        deps.logger.debug('[ptt] onStart while active — preempting', {\n          old: active.sessionId,\n          new: sessionId,\n        });\n        try {\n          await deps.audioCapture.cancel();\n        } catch (err) {\n          deps.logger.warn('[ptt] cancel failed during preempt', { err: String(err) });\n        }\n        if (active.watchdogTimer) clearTimeout(active.watchdogTimer);\n        active = null;\n      }\n\n      // Claim the slot BEFORE any awaits so concurrent onStart calls preempt\n      // this in-progress session rather than racing with it.\n      active = {\n        sessionId,\n        startedAtMs: deps.now(),\n        watchdogTimer: null,\n        finalizedByWatchdog: false,\n      };\n      const claimed = active;\n\n      await deps.playChime('open');\n      await deps.showOverlay(true, sessionId);\n","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/app/src/services/pttService.ts#L167-L203","documentation":"While starting a new push-to-talk session, a previous session was active and had to be preempted, but cancelling its audio capture (deps.audioCapture.cancel) threw. The warn is non-fatal to the new session — preemption continues and the new session claims the slot — but the old capture stream may still be running, potentially leaking microphone audio or producing a stale finalized session later.","triggerScenarios":"Thrown at app/src/services/pttService.ts:185 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Inspect err to determine whether the audio device was already stopped or the capture backend errored","Check for orphaned capture sessions (a stale onStop for the old session is tolerated and logged as 'stale onStop — ignored')","If preemption failures recur, verify the audio capture backend implementation handles cancel-while-starting and cancel-after-stop states","Confirm microphone device state — a device that disappeared mid-session can make cancel fail"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}