{"record":{"id":"c5422ed3c415136f","repo":"mastra-ai/mastra","slug":"frame-dimensions-changed-during-recording-expecte","errorCode":null,"errorMessage":"Frame dimensions changed during recording: expected ${width}x${height}, got ${rgba.width}x${rgba.height}","messagePattern":"Frame dimensions changed during recording: expected (.+?)x(.+?), got (.+?)x(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/browser/recording/tools.ts","lineNumber":185,"sourceCode":" */\nfunction encodeFramesAsAvi(\n  state: RecordingState,\n  outputPath: string,\n): { width: number; height: number; written: number } {\n  if (state.frames.length === 0) {\n    throw new Error('No frames captured during recording');\n  }\n\n  // Inspect the first frame to learn the dimensions for the AVI header.\n  const firstRgba = decodeJpeg(state.frames[0]!.bytes);\n  const width = firstRgba.width;\n  const height = firstRgba.height;\n\n  const muxFrames: MjpegFrame[] = [];\n  for (const frame of state.frames) {\n    const rgba = decodeJpeg(frame.bytes);\n    if (rgba.width !== width || rgba.height !== height) {\n      throw new Error(\n        `Frame dimensions changed during recording: expected ${width}x${height}, got ${rgba.width}x${rgba.height}`,\n      );\n    }\n    const out = buildCaptionedFrame(state, frame);\n    muxFrames.push(out);\n  }\n\n  writeMjpegAviFile(outputPath, muxFrames, { width, height });\n  return { width, height, written: muxFrames.length };\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle helpers\n// ---------------------------------------------------------------------------\n\nasync function startRecording(\n  browser: MastraBrowser,\n  opts: {","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/browser/recording/tools.ts#L167-L203","documentation":"An MJPEG AVI fixes the video dimensions in its stream header, so all frames must share the same size. encodeFramesAsAvi decodes each frame and throws if any frame's dimensions differ from the first frame's, preventing a visually corrupt video.","triggerScenarios":"The browser viewport was resized mid-recording; a frame was captured at devicePixelRatio different from the first; full-page capture changed height as content grew.","commonSituations":"Tests that call page.setViewportSize while recording; responsive-layout resizing; capturing full-page screenshots of a page that grows during the session; DPR changes from moving the window across monitors.","solutions":["Lock the viewport (page.setViewportSize) before startRecording and never resize during capture","Use viewport-sized (not full-page) screenshots for the recording","Keep devicePixelRatio constant — don't move windows across displays with different scaling mid-recording","If resize is unavoidable, stop and start a new recording per dimension"],"exampleFix":"// before\nawait page.setViewportSize({ width: 1280, height: 720 }); // mid-recording\n// after\nawait page.setViewportSize({ width: 1280, height: 720 });\nawait browser_record({ action: 'start' });\n// ... no resize calls while recording ...\nawait browser_record({ action: 'stop' });","handlingStrategy":"validation","validationCode":"const dims = new Set();\nfor (const f of state.frames) {\n  const { width, height } = decodeJpeg(f.bytes);\n  dims.add(`${width}x${height}`);\n}\nif (dims.size > 1) throw new Error(`mixed frame sizes: ${[...dims].join(', ')}`);","typeGuard":"function allFramesSameSize(frames) {\n  if (frames.length === 0) return true;\n  const { width, height } = decodeJpeg(frames[0].bytes);\n  return frames.every(f => {\n    const r = decodeJpeg(f.bytes);\n    return r.width === width && r.height === height;\n  });\n}","tryCatchPattern":"try {\n  await browser_record({ action: 'stop' });\n} catch (e) {\n  if (e.message.startsWith('Frame dimensions changed during recording')) {\n    // drop mismatched frames or split into multiple AVIs\n  } else throw e;\n}","preventionTips":["Lock viewport size before recording; never resize mid-recording","Use viewport screenshots, not full-page, during recording","Keep devicePixelRatio constant for the session"],"tags":["recording","dimensions","avi","viewport"],"backgroundTag":"frame-dimension-mismatch","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}