{"record":{"id":"f56a6a34a99fa190","repo":"can1357/oh-my-pi","slug":"app-surface-must-be-a-surface-uuid-e-g-cmux-surf","errorCode":null,"errorMessage":"app.surface must be a surface UUID (e.g. CMUX_SURFACE_ID), not a 'surface:N' ref; omit it to open a new split","messagePattern":"app\\.surface must be a surface UUID \\(e\\.g\\. CMUX_SURFACE_ID\\), not a 'surface:N' ref; omit it to open a new split","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-supervisor.ts","lineNumber":425,"sourceCode":"\t\townerSessionId: opts.ownerSessionId,\n\t};\n\tworker.onMessage(msg => handleTabMessage(tab, msg));\n\ttabs.set(name, tab);\n\t// Durably record ownership so another live omp process can reap this page if\n\t// this process dies abnormally before its own teardown closes the tab.\n\tconst scope = sharedScopeOf(browser);\n\tif (scope) void recordSharedTarget(scope, info.targetId);\n\treturn { tab, created: true };\n}\n\nasync function acquireCmuxTab(\n\tname: string,\n\tbrowser: CmuxBrowserHandle,\n\topts: AcquireTabOptions,\n): Promise<AcquireTabResult> {\n\tconst attachedSurface = opts.cmuxSurface ?? browser.surface;\n\tif (attachedSurface?.startsWith(\"surface:\")) {\n\t\tthrow new ToolError(\n\t\t\t\"app.surface must be a surface UUID (e.g. CMUX_SURFACE_ID), not a 'surface:N' ref; omit it to open a new split\",\n\t\t);\n\t}\n\n\tlet surfaceId = attachedSurface;\n\tlet initialUrl = opts.url;\n\tlet ownsSurface = false;\n\ttry {\n\t\tif (!surfaceId) {\n\t\t\tconst params: Record<string, unknown> = { url: opts.url ?? \"about:blank\", focus: false };\n\t\t\tif (process.env.CMUX_WORKSPACE_ID) params.workspace_id = process.env.CMUX_WORKSPACE_ID;\n\t\t\tif (process.env.CMUX_SURFACE_ID) params.surface_id = process.env.CMUX_SURFACE_ID;\n\t\t\tconst result = await browser.client.request(\"browser.open_split\", params, { timeoutMs: opts.timeoutMs });\n\t\t\tif (typeof result.surface_id !== \"string\" || result.surface_id.length === 0) {\n\t\t\t\tthrow new ToolError(\"cmux browser.open_split did not return a surface_id\");\n\t\t\t}\n\t\t\tsurfaceId = result.surface_id;\n\t\t\townsSurface = true;","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-supervisor.ts#L407-L443","documentation":"When opening a cmux-attached tab, the resolved surface identifier must be a raw surface UUID. If it starts with the legacy 'surface:' ref prefix, the library refuses it because the cmux API expects a UUID in app.surface (e.g. CMUX_SURFACE_ID). Omitting app.surface opens a new split instead.","triggerScenarios":"Calling browser open with cmuxSurface set (or a browser handle whose .surface carries) a value like 'surface:3' instead of the UUID that CMUX_SURFACE_ID exposes.","commonSituations":"Copying a surface ref from cmux UI/logs instead of reading the CMUX_SURFACE_ID env var; stale code passing the old 'surface:N' format after a cmux API change; hardcoding a ref captured from a previous session.","solutions":["Pass the raw UUID (value of CMUX_SURFACE_ID) as the surface instead of a 'surface:N' ref.","Omit the surface option entirely so the call opens a new split.","Convert at the boundary: strip/resolve the 'surface:' prefix to its UUID before calling the tool.","Update stored configuration/scripts that still record surface refs in the old format."],"exampleFix":"// before\nawait browserTool({ action: \"open\", cmuxSurface: \"surface:3\" });\n// after\nawait browserTool({ action: \"open\", cmuxSurface: process.env.CMUX_SURFACE_ID }); // raw UUID","handlingStrategy":"validation","validationCode":"const surface = opts.cmuxSurface ?? process.env.CMUX_SURFACE_ID;\nif (surface && surface.startsWith(\"surface:\")) {\n  throw new Error(`Pass the surface UUID, not '${surface}'; omit to open a new split`);\n}","typeGuard":"function isSurfaceUuid(v: string): boolean {\n  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(v);\n}","tryCatchPattern":null,"preventionTips":["Always source surfaces from CMUX_SURFACE_ID (UUID), never from UI 'surface:N' refs","Validate format before passing: reject values containing 'surface:'","Prefer omitting the surface when a new split is acceptable"],"tags":["validation","cmux","argument-error"],"backgroundTag":"invalid-surface-ref-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}