JuliusBrussee/caveman · error
browser function returned no result object
Error message
browser function returned no result object
What it means
Returned by callOnNodeRaw() when runtime.CallFunctionOn completes without error and without an exception but yields a nil result RemoteObject. Distinct from 'browser function threw' (exception present) and from decodeBoolObject's 'browser returned no result object' (higher up); here the raw evaluation path got nothing back, which happens when the function returns undefined or the context is torn down around the call. The driver fails closed rather than nil-deref.
Source
Thrown at browse/cdp.go:418
var exception *runtime.ExceptionDetails
if err := chromedp.Run(ctx, chromedp.ActionFunc(func(actionCtx context.Context) error {
obj, err := dom.ResolveNode().WithBackendNodeID(cdp.BackendNodeID(target.BackendDOMNodeID)).Do(actionCtx)
if err != nil {
return err
}
if obj == nil {
return errors.New("resolve node returned no object")
}
res, exception, err = runtime.CallFunctionOn(fn).WithObjectID(obj.ObjectID).Do(actionCtx)
return err
})); err != nil {
return nil, err
}
if exception != nil {
return nil, errors.New("browser function threw")
}
if res == nil {
return nil, errors.New("browser function returned no result object")
}
return res, nil
}
func jsString(s string) string {
b, _ := json.Marshal(s)
return string(b)
}
func DefaultUserDataDir(home string) string {
if home == "" {
if h, err := os.UserHomeDir(); err == nil {
home = filepath.Join(h, ".caveman")
}
}
if home == "" {
return ""
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Make the injected function explicitly return a value (return document.activeElement !== this; not just the comparison as a statement body that gets dropped).
- If the function already returns, re-snapshot and retry once — a torn-down context can swallow results.
- Test the function body standalone via eval on the same node to confirm it produces a value.
Example fix
// before — function body has no return
`function(){ this.focus(); }`
// after
`function(){ this.focus(); return document.activeElement === this; }` Defensive patterns
Strategy: type-guard
Validate before calling
// Go: when writing injected functions, always return a value
// bad: function(){ this.focus(); }
// good: function(){ this.focus(); return document.activeElement === this; } Type guard
func hasResult(res *runtime.RemoteObject) (*runtime.RemoteObject, error) {
if res == nil {
return nil, errors.New("browser function returned no result object")
}
return res, nil
} Try / catch
// Go
res, err := d.callOnNodeRaw(ctx, target, fn)
if err != nil {
if strings.Contains(err.Error(), "returned no result object") {
// likely undefined return: fix fn to return, then one retry after re-snapshot
return fixFnAndRetry(ctx, target, fn)
}
return nil, err
} Prevention
- Every function string passed to callOnNode/callOnNodeRaw must end in an explicit `return`.
- Nil-check the RemoteObject on every CDP result path; Chrome can return nil without error.
- Validate injected JS in an eval tool first when porting console snippets.
When it happens
Trigger: An on-node evaluation whose function implicitly returns undefined (missing return statement), or a call racing context destruction so Chrome drops the result silently.
Common situations: Custom probe functions written as statements instead of expressions forgetting to return; eval helpers reused from console (where undefined results are normal) pasted into act paths; navigation racing the eval.
Related errors
- browser returned no result object
- resolve node returned no object
- browser function threw
- select: missing option
- missing backend DOM node id
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/e7706afabe3657ac.
Report an issue: GitHub.