microsoft/playwright · error
Screencast is already running
Error message
Screencast is already running
What it means
Only one active frame-capture mechanism is allowed per page at a time. PageDispatcher.screencastStart throws when either _screencastClient (an in-progress MCP/protocol screencast) or _videoRecorder (a context-level video recording) is already set. The two subsystems share the page's frame producer and cannot run concurrently.
Solutions
- Call screencastStop (or page._screencast.stop) before starting a new screencast on the same page.
- Do not combine context.recordVideo with page-level screencast — pick one capture mechanism.
- Wrap screencast usage in try/finally so screencastStop always runs even on test failure.
- Use a fresh page for each screencast session if stop ordering is hard to guarantee.
Example fix
// before
await page.screencastStart({ format: 'jpeg', quality: 80 });
// ...later, another call without stop
await page.screencastStart({ format: 'jpeg', quality: 80 }); // throws
// after
await page.screencastStart({ format: 'jpeg', quality: 80 });
try { /* ... */ } finally { await page.screencastStop(); }
await page.screencastStart({ format: 'jpeg', quality: 80 }); Defensive patterns
Strategy: validation
Validate before calling
// Stop any running screencast before starting a new one.
await page.screencastStop().catch(() => {});
await page.screencastStart({ format: 'jpeg', quality: 80 }); Prevention
- Do not combine context.recordVideo with page screencast.
- Wrap screencast use in try/finally and always call screencastStop.
- Start each screencast on a fresh page if stop ordering is uncertain.
When it happens
Trigger: Calling screencastStart a second time without first calling screencastStop; starting a page screencast while the browser context was created with recordVideo; starting recordVideo after a screencast is already streaming frames.
Common situations: MCP tooling that starts a screencast for visual feedback while the test config also has use: { recordVideo: { dir } }; a previous test's screencast was not stopped because the test errored mid-way; re-invoking a screencast command on a page that already has one running.
Related errors
- "fps" must be a positive number, got
- File must have .webm extension
- "recordVideo.fps" must be a positive number, got
- Video recording has already been started.
AI-assisted analysis of microsoft/playwright@f1d33b5029 (2026-09-21).
Data as JSON: /api/errors/e14b6e38132f0bb8.
Report an issue: GitHub.
Appendix: source
Thrown at packages/playwright-core/src/server/dispatchers/pageDispatcher.ts:399
async screencastChapter(params: channels.PageScreencastChapterParams): Promise<channels.PageScreencastChapterResult> {
await this._page.overlay.chapter(params);
}
async screencastSetOverlayVisible(params: channels.PageScreencastSetOverlayVisibleParams): Promise<channels.PageScreencastSetOverlayVisibleResult> {
await this._page.overlay.setVisible(params.visible);
}
async screencastShowActions(params: channels.PageScreencastShowActionsParams): Promise<channels.PageScreencastShowActionsResult> {
this._page.screencast.showActions({ duration: params.duration, position: params.position, fontSize: params.fontSize, cursor: params.cursor, style: params.style });
}
async screencastHideActions(): Promise<channels.PageScreencastHideActionsResult> {
this._page.screencast.hideActions();
}
async screencastStart(params: channels.PageScreencastStartParams, progress?: Progress): Promise<channels.PageScreencastStartResult> {
if (this._screencastClient || this._videoRecorder)
throw new Error('Screencast is already running');
if (params.fps !== undefined && params.fps <= 0)
throw new Error(`"fps" must be a positive number, got ${params.fps}`);
if (params.sendFrames) {
this._screencastClient = {
onFrame: async (frame: ScreencastFrame) => {
const frameId = ++this._screencastFrameId;
const promise = new ManualPromise<void>();
this._screencastFrameAcks.set(frameId, promise);
this._dispatchEvent('screencastFrame', { frameId, data: frame.buffer, timestamp: frame.frameSwapWallTime, viewportWidth: frame.viewportWidth, viewportHeight: frame.viewportHeight });
await promise;
},
gracefulClose: () => this._clearScreencastFrameAcks(),
dispose: () => this._clearScreencastFrameAcks(),
size: params.size,
quality: params.quality,
};
this._page.screencast.addClient(this._screencastClient);View on GitHub (pinned to f1d33b5029)