microsoft/playwright · error

"fps" must be a positive number, got

Error message

"fps" must be a positive number, got ${params.fps}

What it means

The PageScreencastStart dispatcher validates the requested frames-per-second before starting a page screencast session. A non-positive fps (0 or negative) cannot drive frame capture, so the server rejects the request before any screencast client or video recorder is attached.

Solutions

  1. Pass a positive fps value (e.g. 25) when starting the screencast.
  2. Omit fps from params to use the server default.
  3. Clamp/validate user- or config-supplied fps before issuing the call.
  4. If a screencast/video recording is already running, stop it first (that produces the related 'Screencast is already running' error).

Example fix

// before
await page.screencastStart({ fps: 0 });
// after
await page.screencastStart({ fps: 25 });
Defensive patterns

Strategy: validation

Validate before calling

if (fps !== undefined && (!(typeof fps === 'number') || fps <= 0))
  throw new Error(`fps must be a positive number, got ${fps}`); // validate before calling screencastStart

Type guard

function isValidScreencastFps(fps: unknown): fps is number {
  return typeof fps === 'number' && Number.isFinite(fps) && fps > 0;
}

Try / catch

try {
  await page.screencastStart({ fps });
} catch (e) {
  if ((e as Error).message.includes('"fps" must be a positive number')) {
    await page.screencastStart({}); // retry with default fps
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the screencast start API (Page.screencastStart protocol / page screencast entry point) with params.fps set to 0 or a negative number.

Common situations: Feeding fps from a computed value that resolves to 0, translating config where 0 meant 'default', or wiring a custom client to the internal screencast API with unvalidated user input.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of microsoft/playwright@f1d33b5029 (2026-09-21). Data as JSON: /api/errors/5b7a9ae5ca8895c9. Report an issue: GitHub.

Appendix: source

Thrown at packages/playwright-core/src/server/dispatchers/pageDispatcher.ts:401

  }

  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)