{"record":{"id":"a12b3b29913171e5","repo":"JuliusBrussee/caveman","slug":"browser-function-threw","errorCode":null,"errorMessage":"browser function threw","messagePattern":"browser function threw","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"browse/cdp.go","lineNumber":415,"sourceCode":"\t\treturn nil, errors.New(\"missing backend DOM node id\")\n\t}\n\tvar res *runtime.RemoteObject\n\tvar exception *runtime.ExceptionDetails\n\tif err := chromedp.Run(ctx, chromedp.ActionFunc(func(actionCtx context.Context) error {\n\t\tobj, err := dom.ResolveNode().WithBackendNodeID(cdp.BackendNodeID(target.BackendDOMNodeID)).Do(actionCtx)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif obj == nil {\n\t\t\treturn errors.New(\"resolve node returned no object\")\n\t\t}\n\t\tres, exception, err = runtime.CallFunctionOn(fn).WithObjectID(obj.ObjectID).Do(actionCtx)\n\t\treturn err\n\t})); err != nil {\n\t\treturn nil, err\n\t}\n\tif exception != nil {\n\t\treturn nil, errors.New(\"browser function threw\")\n\t}\n\tif res == nil {\n\t\treturn nil, errors.New(\"browser function returned no result object\")\n\t}\n\treturn res, nil\n}\n\nfunc jsString(s string) string {\n\tb, _ := json.Marshal(s)\n\treturn string(b)\n}\n\nfunc DefaultUserDataDir(home string) string {\n\tif home == \"\" {\n\t\tif h, err := os.UserHomeDir(); err == nil {\n\t\t\thome = filepath.Join(h, \".caveman\")\n\t\t}\n\t}","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/browse/cdp.go#L397-L433","documentation":"Returned by callOnNodeRaw() when runtime.CallFunctionOn reports non-nil ExceptionDetails — the injected JavaScript function threw inside the page. The comment deliberately discards the details object, so the Go-side message is generic; the actual exception (e.g. 'option not found' from the select action's matcher, or any throw in a custom eval function) happened in browser JS.","triggerScenarios":"The select action's inline function throwing 'option not found' because no <option> matches the given value/label/text; a custom eval/on-node function that throws (TypeError on unexpected DOM shape, accessing removed nodes); assertion-style helpers that throw to signal failure.","commonSituations":"Selecting an option whose label changed or that does not exist in this <select>; evaluating functions against a DOM that re-rendered mid-call; brittle selectors assuming child structure that changed.","solutions":["For select: verify the exact option value/label via snapshot or eval before selecting; the match checks value, then label, then trimmed textContent.","For custom functions: run the same expression via an eval tool to see the real JS exception (this error intentionally hides it), then fix the function.","Add existence guards in your injected JS (return a sentinel instead of throwing) if you need to distinguish 'not found' from hard failure."],"exampleFix":"// before\nact(target: \"s3\", action: \"select\", option: \"USA\")  // label is \"United States\"\n\n// after\nact(target: \"s3\", action: \"select\", text: \"United States\")","handlingStrategy":"try-catch","validationCode":"// Go: confirm the option exists before selecting\nconst probe = `function(){ const w = %s; return Array.from(this.options||[]).some(o => o.value === w || o.label === w || o.textContent.trim() === w); }`","typeGuard":null,"tryCatchPattern":"// Go: the Go error hides details; re-run the same expression via eval to surface the JS exception\nif err != nil && strings.Contains(err.Error(), \"browser function threw\") {\n    detail, _ := d.eval(ctx, fn) // log detail, fix the JS or the option string\n    return fmt.Errorf(\"browser function threw: %s\", detail)\n}","preventionTips":["Match select options on their exact value first; fall back to label, then trimmed text.","Return sentinel values from injected JS instead of throwing when 'not found' is an expected outcome.","Smoke-test injected function bodies with an eval call before wiring them into actions."],"tags":["browser","cdp","javascript","dom","select"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}