{"record":{"id":"f2ae006f9e7e4f98","repo":"mastra-ai/mastra","slug":"no-frames-captured-during-recording","errorCode":null,"errorMessage":"No frames captured during recording","messagePattern":"No frames captured during recording","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/browser/recording/tools.ts","lineNumber":173,"sourceCode":"  }\n  const rgba = decodeJpeg(frame.bytes);\n  drawCaptionOnFrame(rgba, caption.text);\n  return { bytes: encodeJpeg(rgba, 80), timestampMs: frame.timestampMs };\n}\n\n/**\n * Encode all buffered frames as an MJPEG AVI file written directly to disk.\n *\n * Returns the dimensions of the first frame (used to populate the AVI header).\n * The AVI stream has one fixed frame size, so fail fast if the browser changes\n * screencast dimensions mid-recording.\n */\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  }","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/browser/recording/tools.ts#L155-L191","documentation":"encodeFramesAsAvi refuses to encode a recording with zero captured frames, throwing before writeMjpegAviFile. An AVI with no video stream is invalid, so stopping a recording that captured nothing fails loudly instead of producing an empty file.","triggerScenarios":"Calling browser_record action=\"stop\" before any screenshot interval fired — e.g. stopping within milliseconds of start, or capture never ran due to page/capture errors.","commonSituations":"Start/stop race in test scripts; screen-capture permission denied so zero frames were collected; browser tab closed immediately; very small maxDurationMs.","solutions":["Keep the recording alive long enough for at least one capture interval","Verify capture permissions and that the page stays open during recording","Check state.frames.length before stopping, or catch this error and treat the recording as empty"],"exampleFix":"// before\nawait browser_record({ action: 'start' });\nawait browser_record({ action: 'stop' }); // may have 0 frames\n// after\nawait browser_record({ action: 'start' });\nawait new Promise(r => setTimeout(r, 500)); // allow ≥1 frame\nawait browser_record({ action: 'stop' });","handlingStrategy":"try-catch","validationCode":"if (state.frames.length === 0) {\n  throw new Error('nothing to encode: recording captured no frames');\n}","typeGuard":"function hasCapturedFrames(state) {\n  return Array.isArray(state.frames) && state.frames.length > 0;\n}","tryCatchPattern":"try {\n  await browser_record({ action: 'stop' });\n} catch (e) {\n  if (e.message === 'No frames captured during recording') {\n    // record as empty session, check capture permissions\n  } else throw e;\n}","preventionTips":["Wait at least one capture interval before stopping","Verify screen-capture permissions before startRecording","Keep the page open for the whole recording"],"tags":["recording","frames","avi","empty-state"],"backgroundTag":"empty-frame-recording","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}