{"record":{"id":"0ba101fde44af298","repo":"microsoft/playwright","slug":"recording-is-already-in-progress-browsercontextdispatcher","errorCode":null,"errorMessage":"Recording is already in progress.","messagePattern":"Recording is already in progress\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts","lineNumber":361,"sourceCode":"  async storageState(params: channels.BrowserContextStorageStateParams, progress: Progress): Promise<channels.BrowserContextStorageStateResult> {\n    return await this._context.storageState(progress, params);\n  }\n\n  async setStorageState(params: channels.BrowserContextSetStorageStateParams, progress: Progress): Promise<void> {\n    await this._context.setStorageState(progress, params.storageState, 'api');\n  }\n\n  async close(params: channels.BrowserContextCloseParams, progress: Progress): Promise<void> {\n    await this._context.close(progress, params);\n  }\n\n  async showRecorder(params: channels.BrowserContextShowRecorderParams, progress: Progress): Promise<void> {\n    await progress.race(RecorderApp.show(this._context, params));\n  }\n\n  async startRecording(params: channels.BrowserContextStartRecordingParams, progress: Progress): Promise<void> {\n    if (this._recorderApp)\n      throw new Error('Recording is already in progress.');\n    // Recorder events only go to the connection that started the recording.\n    this._recorderApp = await progress.race(ProgrammaticRecorderApp.start(this._context, params, ({ event, data, page, code }) => {\n      this._dispatchEvent('recorderEvent', { event, data, code, page: PageDispatcher.from(this, page) });\n    }));\n  }\n\n  async stopRecording(params: channels.BrowserContextStopRecordingParams, progress: Progress): Promise<void> {\n    const recorderApp = this._recorderApp;\n    this._recorderApp = undefined;\n    if (recorderApp)\n      await progress.race(recorderApp.stop());\n  }\n\n  async exposeConsoleApi(params: channels.BrowserContextExposeConsoleApiParams, progress: Progress): Promise<void> {\n    await this._context.exposeConsoleApi(progress);\n  }\n\n  async pause(params: channels.BrowserContextPauseParams, progress: Progress) {","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/microsoft/playwright/blob/500c9c822ce7664539a4c8a88810048dfe090c3b/packages/playwright-core/src/server/dispatchers/browserContextDispatcher.ts#L343-L379","documentation":"BrowserContextDispatcher allows only one active recording session per context. startRecording stores the RecorderApp in this._recorderApp; if it is already set, a programmatic recording is running and a second startRecording call is rejected. Stop the current recording first.","triggerScenarios":"Calling context.startRecording() (via the BrowserContext channel) twice without calling stopRecording() in between.","commonSituations":"Test harnesses or tools that kick off codegen/recording per test but only stop it conditionally; retry logic re-invoking startRecording after a partial failure that left the recorder attached.","solutions":["Call context.stopRecording() (or the stopRecording channel method) before starting again.","Guard the start call in your code so startRecording is invoked at most once per context.","Create a fresh browser context for each recording session."],"exampleFix":"// before\nawait context.startRecording({ language: 'javascript' });\nawait context.startRecording({ language: 'javascript' });\n// after\nawait context.startRecording({ language: 'javascript' });\nawait context.stopRecording();\nawait context.startRecording({ language: 'javascript' });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await context.startRecording({ language: 'javascript' });\n} catch (e) {\n  if (e.message.includes('Recording is already in progress')) {\n    await context.stopRecording();\n    await context.startRecording({ language: 'javascript' });\n  } else throw e;\n}","preventionTips":["Track recording state in your harness and stop before every start.","Use one browser context per recording session."],"tags":["recorder","codegen","state-conflict","browser-context"],"backgroundTag":"invalid-state-transition","analyzedSha":"500c9c822ce7664539a4c8a88810048dfe090c3b","analyzedAt":"2026-09-15T07:37:15.003Z","contentChangedAt":"2026-09-15T07:37:15.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}