mastra-ai/mastra · error
A browser recording is already active. Call browser_record w
Error message
A browser recording is already active. Call browser_record with action="stop" before starting a new recording.
What it means
The recording module tracks a single active RecordingState; startRecording throws if one is already in progress. Recordings are exclusive, so the caller must stop the current one (browser_record action="stop") before starting a new one.
Source
Thrown at packages/core/src/browser/recording/tools.ts:214
// ---------------------------------------------------------------------------
// Lifecycle helpers
// ---------------------------------------------------------------------------
async function startRecording(
browser: MastraBrowser,
opts: {
maxDurationMs?: number;
everyNthFrame?: number;
maxWidth?: number;
maxHeight?: number;
outputPath?: string;
threadId?: string;
outputDir: string;
},
): Promise<{ id: string; outputPath: string; maxDurationMs: number }> {
if (active) {
throw new Error(
'A browser recording is already active. Call browser_record with action="stop" before starting a new recording.',
);
}
const maxDurationMs = Math.min(
HARD_CAP_MAX_DURATION_MS,
Math.max(1_000, opts.maxDurationMs ?? DEFAULT_MAX_DURATION_MS),
);
const everyNthFrame = Math.max(1, Math.floor(opts.everyNthFrame ?? DEFAULT_EVERY_NTH_FRAME));
const maxWidth = Math.max(160, Math.floor(opts.maxWidth ?? DEFAULT_MAX_WIDTH));
const maxHeight = Math.max(120, Math.floor(opts.maxHeight ?? DEFAULT_MAX_HEIGHT));
const id = generateRecordingId();
const outputPath = resolveOutputPath(id, opts.outputDir, opts.outputPath);
let stream: ScreencastStream;
try {
// Bind screencast to the same thread/page the agent is interacting with.View on GitHub (pinned to 75dd419e61)
Solutions
- Call browser_record with action="stop" before starting a new recording
- Ensure test cleanup (afterEach) always stops an active recording, even on failure
- Avoid running recordings concurrently in the same process/worker
- Catch this error on start to detect and recover from a leaked active recording
Example fix
// before
await browser_record({ action: 'start' });
await browser_record({ action: 'start' }); // throws
// after
await browser_record({ action: 'start' });
await browser_record({ action: 'stop' });
await browser_record({ action: 'start' }); Defensive patterns
Strategy: try-catch
Validate before calling
null
Try / catch
try {
await browser_record({ action: 'start' });
} catch (e) {
if (e.message.includes('already active')) {
await browser_record({ action: 'stop' });
await browser_record({ action: 'start' });
} else throw e;
} Prevention
- Always pair start with stop, including in test cleanup (afterEach/finally)
- Never start a recording while another may be active in the same process
- Avoid sharing recording state across concurrent test workers
When it happens
Trigger: Calling browser_record action="start" twice without an intervening "stop"; a previous recording that never stopped (crashed test, forgotten cleanup); parallel test workers sharing the module state.
Common situations: Retry wrappers that re-run a start step after a mid-test failure; concurrent tests in the same process; a stop call that threw earlier leaving state.active set (note: autoStopTimer usually clears it).
Related errors
- tool_result must be preceded by a tool_call
- MastraFactory.prepare() called twice
- Factory kickoff lease was lost before completion.
- Could not create the session. Reload the page and try again.
- Plugin "${pluginId}" is not installed in ${scope} scope
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/bcfc0e2ba085ae11.
Report an issue: GitHub.