JuliusBrussee/caveman · error

browser returned no result object

Error message

browser returned no result object

What it means

Returned by decodeBoolObject() when a runtime.CallFunctionOn result is a nil *runtime.RemoteObject. Per the code comment, CallFunctionOn can return nil without an error; dereferencing res.Value there would nil-panic and — through the MCP panic hole — kill the whole process (issue #140). So the helper fails closed with this error instead of crashing.

Source

Thrown at browse/cdp.go:386

	_, err := d.callOnNodeRaw(ctx, target, fn)
	return err
}

func (d *CDPDriver) callBoolOnNode(ctx context.Context, target Target, fn string) (bool, error) {
	res, err := d.callOnNodeRaw(ctx, target, fn)
	if err != nil {
		return false, err
	}
	return decodeBoolObject(res)
}

// decodeBoolObject reads a boolean out of a CallFunctionOn result, failing
// closed on a nil object. CallFunctionOn can return a nil RemoteObject without
// an error; dereferencing res.Value there would nil-panic and, through the MCP
// panic hole, kill the whole process (issue #140).
func decodeBoolObject(res *runtime.RemoteObject) (bool, error) {
	if res == nil {
		return false, errors.New("browser returned no result object")
	}
	var out bool
	if err := json.Unmarshal(res.Value, &out); err != nil {
		return false, err
	}
	return out, nil
}

func (d *CDPDriver) callOnNodeRaw(ctx context.Context, target Target, fn string) (*runtime.RemoteObject, error) {
	if target.BackendDOMNodeID <= 0 {
		return nil, errors.New("missing backend DOM node id")
	}
	var res *runtime.RemoteObject
	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

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Retry the action after a fresh snapshot — a destroyed context is usually transient and the new handle re-resolves.
  2. If it reproduces on one element consistently, the element's frame/context is being torn down (redirect loop, aggressive rerender); stabilize the page state first.
  3. Do not 'handle' it by ignoring the error: it is deliberately failing closed where older code would have panic-killed the MCP server.
Defensive patterns

Strategy: try-catch

Try / catch

// Go: fail closed on nil RemoteObject instead of dereferencing
res, err := d.callOnNodeRaw(ctx, target, fn)
if err != nil {
    if strings.Contains(err.Error(), "no result object") {
        // context likely destroyed: re-snapshot once, then give up cleanly
        return retryAfterSnapshot(ctx, target, fn)
    }
    return false, err
}

Prevention

When it happens

Trigger: Any boolean-returning callOnNode evaluation (actionability checks, visibility predicates) where Chrome returns no remote object: target detached mid-call, execution context destroyed by navigation, or the evaluated function returning undefined.

Common situations: Page navigates or redirects while an actionability check runs; SPA route change destroying the frame's context; element removed by a script between snapshot and act.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/3d87e985a77c3c35. Report an issue: GitHub.