{"record":{"id":"5b29316fcaa22806","repo":"can1357/oh-my-pi","slug":"label-threw-a-javascript-exception-n-value","errorCode":null,"errorMessage":"${label} threw a JavaScript exception:\\n${value.__ompErr}","messagePattern":"(.+?) threw a JavaScript exception:\\\\n(.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/cmux/rpc.ts","lineNumber":160,"sourceCode":"\t\t\tconst __v = (${expr});\n\t\t\tif (__v && typeof __v.then === \"function\") return { __ompPromise: true };\n\t\t\treturn { __ompOk: __v === undefined ? null : __v };\n\t\t} catch (e) {\n\t\t\treturn { __ompErr: (e && (e.stack || e.message)) || String(e) };\n\t\t}\n\t})()`;\n}\n\n/**\n * Decode a {@link serializeEvalWithEnvelope} result: rethrow page-side\n * exceptions as rich {@link ToolError}s, reject unserializable Promise\n * returns with an actionable message, and pass through values from daemons\n * that did not run the wrapper.\n */\nexport function unwrapEvalEnvelope<TResult>(value: unknown, label: string): TResult {\n\tif (value && typeof value === \"object\") {\n\t\tif (\"__ompErr\" in value && typeof value.__ompErr === \"string\") {\n\t\t\tthrow new ToolError(`${label} threw a JavaScript exception:\\n${value.__ompErr}`);\n\t\t}\n\t\tif (\"__ompPromise\" in value && value.__ompPromise === true) {\n\t\t\tthrow new ToolError(\n\t\t\t\t`${label} returned a Promise, but this surface evaluates synchronously and cannot await it — return a plain value (poll with waitForFunction for async state instead)`,\n\t\t\t);\n\t\t}\n\t\tif (\"__ompOk\" in value) {\n\t\t\treturn value.__ompOk as TResult;\n\t\t}\n\t}\n\treturn value as TResult;\n}\n\nexport function mapWaitUntil(waitUntil: string | undefined): \"interactive\" | \"complete\" {\n\treturn waitUntil === \"domcontentloaded\" ? \"interactive\" : \"complete\";\n}\n\nexport interface ResolveCmuxKindOptions {","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/cmux/rpc.ts#L142-L178","documentation":"`unwrapEvalEnvelope` inspects values returned by cmux eval RPCs. The in-page wrapper serializes a thrown exception as `{ __ompErr: \"<stack/message>\" }`; when seen, this function rethrows it as a ToolError `<label> threw a JavaScript exception:` followed by the original error text. It converts silent in-page JS failures into actionable host-side errors for `evaluate`/`evaluateOnSelector`.","triggerScenarios":"The script passed to tab.evaluate/evaluateOnSelector throws in the page: TypeError on null querySelector results, syntax errors, reference errors, or calling page-only APIs incorrectly.","commonSituations":"Selector matched nothing and the script dereferences the result; using browser APIs unavailable in the page context; JSON-injected script literals with quoting issues breaking syntax; page CSP or hydration timing.","solutions":["Read the embedded __ompErr text — it names the exact line/exception in your script; fix the script accordingly.","Null-check DOM results inside the script: `const el = document.querySelector(sel); if (!el) return null;`.","Validate the script's syntax (it's a string — an editor/lint pass catches typos) and prefer evaluateOnSelector for element work instead of manual querySelector."],"exampleFix":"// before\ntab.evaluate(`document.querySelector('.price').textContent`);\n// after\ntab.evaluate(`(() => { const el = document.querySelector('.price'); return el ? el.textContent : null; })()`);","handlingStrategy":"try-catch","validationCode":"// validate script syntax before sending\nnew Function(script); // throws SyntaxError locally if the script string is malformed","typeGuard":null,"tryCatchPattern":"try {\n  const price = await tab.evaluate(script);\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes('threw a JavaScript exception')) {\n    console.error('in-page script failed:', err.message.split('\\n').slice(1).join('\\n'));\n    // fall back to a null-safe variant of the script\n  }\n  throw err;\n}","preventionTips":["Write eval scripts as IIFEs with null checks on querySelector results.","Lint the script string (it's plain text — syntax errors only surface in-page).","Prefer evaluateOnSelector / built-in selector actions over hand-written querySelector code.","Return null or a sentinel for missing elements instead of dereferencing blindly."],"tags":["javascript","eval","browser-automation","runtime-error"],"backgroundTag":"evaluated-script-threw","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}