{"record":{"id":"efac5247b248ce6b","repo":"vercel-labs/agent-browser","slug":"screenshot-did-not-return-a-file-path","errorCode":null,"errorMessage":"Screenshot did not return a file path.","messagePattern":"Screenshot did not return a file path\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"skill-data/vercel-sandbox/SKILL.md","lineNumber":53,"sourceCode":"## Screenshot\n\nThe `screenshot --json` command saves to a file and returns the path. Read the file back as base64:\n\n```ts\nexport async function screenshotUrl(url: string) {\n  return withBrowser(async (sandbox) => {\n    await runAgentBrowserCommand(sandbox, [\"open\", url]);\n\n    const titleResult = await runAgentBrowserCommand<{ data?: { title?: string } }>(sandbox, [\n      \"get\", \"title\",\n    ]);\n    const title = titleResult.json?.data?.title || url;\n\n    const ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [\n      \"screenshot\",\n    ]);\n    const ssPath = ssResult.json?.data?.path;\n    if (!ssPath) throw new Error(\"Screenshot did not return a file path.\");\n    const b64Result = await sandbox.runCommand(\"base64\", [\"-w\", \"0\", ssPath]);\n    const screenshot = (await b64Result.stdout()).trim();\n\n    await runAgentBrowserCommand(sandbox, [\"close\"], { json: false });\n\n    return { title, screenshot };\n  });\n}\n```\n\n## Accessibility Snapshot\n\n```ts\nexport async function snapshotUrl(url: string) {\n  return withBrowser(async (sandbox) => {\n    await runAgentBrowserCommand(sandbox, [\"open\", url]);\n\n    const titleResult = await runAgentBrowserCommand<{ data?: { title?: string } }>(sandbox, [","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/vercel-labs/agent-browser/blob/548b159b30eef119ccf6846c8bc807d0eaa3f6f8/skill-data/vercel-sandbox/SKILL.md#L35-L71","documentation":"This throw lives in the example code of the vercel-sandbox skill (skill-data/vercel-sandbox/SKILL.md:53), not in library code. After running `agent-browser screenshot` through runAgentBrowserCommand, the snippet reads ssResult.json?.data?.path and throws when no path string came back. A missing path means the command's stdout was not the expected JSON payload (parseJson in shared.ts returns null on bad JSON) or the JSON lacked data.path.","triggerScenarios":"The screenshot command runs with --json appended automatically (buildAgentBrowserArgv in shared.ts:82-84), so this triggers when the agent-browser CLI inside the sandbox prints non-JSON output (older CLI versions, warnings mixed into stdout), returns a JSON shape without data.path, or when json parsing yields null because stdout is empty (e.g. the command failed in a way that bypassed throwIfCommandFailed, or the CLI version installed via a custom installSpec predates the path-in-JSON behavior).","commonSituations":"Version drift: @agent-browser/sandbox helpers expect the JSON contract of the matching agent-browser CLI, but installSpec pins an older CLI; stdout polluted by shell warnings from the sandbox VM; a CLI that prints the raw path as plain text instead of JSON; invoking the snippet against a session where the screenshot silently failed.","solutions":["Log ssResult.stdout, ssResult.stderr, and ssResult.exitCode right before the throw to see what the CLI actually returned; that distinguishes bad JSON from a missing field.","Remove any custom installSpec pin so the sandbox installs agent-browser at the version matching @agent-browser/sandbox (DEFAULT_AGENT_BROWSER_INSTALL_SPEC in shared.ts:38), or bump the pinned spec to a version that returns { data: { path } } from screenshot --json.","Ensure the screenshot call keeps JSON mode on: call runAgentBrowserCommand(sandbox, [\"screenshot\"]) without { json: false }, which would make stdout non-JSON.","Check that a page is actually open in the session (a prior `open` succeeded and throwIfCommandFailed did not fire) before taking the screenshot."],"exampleFix":"// before\nconst ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [\n  \"screenshot\",\n]);\nconst ssPath = ssResult.json?.data?.path;\nif (!ssPath) throw new Error(\"Screenshot did not return a file path.\");\n\n// after\nconst ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [\n  \"screenshot\",\n]);\nconst ssPath = ssResult.json?.data?.path;\nif (!ssPath) {\n  throw new Error(\n    `Screenshot did not return a file path (exit=${ssResult.exitCode}): ${ssResult.stderr || ssResult.stdout}`,\n  );\n}","handlingStrategy":"type-guard","validationCode":"const ssResult = await runAgentBrowserCommand<{ data?: { path?: string } }>(sandbox, [\n  \"screenshot\",\n]);\n\nif (ssResult.exitCode !== 0) {\n  throw new Error(`screenshot failed (exit ${ssResult.exitCode}): ${ssResult.stderr}`);\n}\nif (ssResult.json === null) {\n  throw new Error(`screenshot stdout was not JSON: ${ssResult.stdout.slice(0, 200)}`);\n}","typeGuard":"interface ScreenshotJson {\n  readonly data?: { readonly path?: string };\n}\n\nfunction hasScreenshotPath(\n  result: AgentBrowserCommandResult<ScreenshotJson>,\n): result is AgentBrowserCommandResult<ScreenshotJson> & {\n  readonly json: ScreenshotJson & { readonly data: { readonly path: string } };\n} {\n  return typeof result.json?.data?.path === \"string\" && result.json.data.path.length > 0;\n}\n\nconst ssResult = await runAgentBrowserCommand<ScreenshotJson>(sandbox, [\"screenshot\"]);\nif (!hasScreenshotPath(ssResult)) {\n  throw new Error(\n    `Screenshot did not return a file path (exit=${ssResult.exitCode}): ${ssResult.stderr || ssResult.stdout}`,\n  );\n}\nconst ssPath = ssResult.json.data.path; // narrowed to string","tryCatchPattern":"try {\n  const b64 = await sandbox.runCommand(\"base64\", [\"-w\", \"0\", ssPath]);\n} catch (error) {\n  if (error instanceof Error && error.message.includes(\"Screenshot did not return a file path\")) {\n    // inspect ssResult.stdout/stderr: usually version drift between helper and CLI\n    throw new Error(\n      `agent-browser CLI returned unexpected screenshot output. Upgrade the CLI install spec. Raw: ${ssResult.stdout.slice(0, 200)}`,\n    );\n  }\n  throw error;\n}","preventionTips":["Keep the agent-browser CLI version inside the sandbox aligned with @agent-browser/sandbox: omit installSpec so DEFAULT_AGENT_BROWSER_INSTALL_SPEC applies.","Always assert exitCode and json !== null on runAgentBrowserCommand results before reading nested fields.","Never call screenshot with { json: false } when you need the path; the JSON payload is the contract for data.path.","Wrap the screenshot step so failures include stdout/stderr context, making sandbox VM output problems diagnosable from logs."],"tags":["screenshot","json","version-mismatch","sandbox","cli"],"backgroundTag":null,"analyzedSha":"548b159b30eef119ccf6846c8bc807d0eaa3f6f8","analyzedAt":"2026-08-16T10:12:14.925Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}