JuliusBrussee/caveman · error
missing backend DOM node id
Error message
missing backend DOM node id
What it means
Returned by CDPDriver.box() when target.BackendDOMNodeID <= 0. Geometry (center x/y, width, height) is fetched via dom.GetBoxModel().WithBackendNodeID, which requires a real backend node id; a Target without one (never resolved from a snapshot, or zero-valued) cannot be measured, so the driver fails closed instead of issuing a CDP call with id 0.
Source
Thrown at browse/cdp.go:303
}
select {
case <-ctx.Done():
return 0, 0, ctx.Err()
case <-time.After(100 * time.Millisecond):
}
}
}
type boxPoint struct {
x float64
y float64
w float64
h float64
}
func (d *CDPDriver) box(ctx context.Context, target Target) (float64, float64, float64, float64, error) {
if target.BackendDOMNodeID <= 0 {
return 0, 0, 0, 0, errors.New("missing backend DOM node id")
}
var model *dom.BoxModel
if err := chromedp.Run(ctx, chromedp.ActionFunc(func(actionCtx context.Context) error {
var err error
model, err = dom.GetBoxModel().WithBackendNodeID(cdp.BackendNodeID(target.BackendDOMNodeID)).Do(actionCtx)
return err
})); err != nil {
return 0, 0, 0, 0, err
}
quad := model.Content
if len(quad) < 8 {
quad = model.Border
}
if len(quad) < 8 {
return 0, 0, 0, 0, errors.New("box model has no quad")
}
minX, maxX := quad[0], quad[0]
minY, maxY := quad[1], quad[1]View on GitHub (pinned to 27d5a3981a)
Solutions
- Take a fresh snapshot (which rebuilds uid -> BackendDOMNodeID mappings) and retry the action with the new uid.
- If you build Target values yourself, resolve them through the driver's snapshot path so BackendDOMNodeID is set.
- Treat this as a stale-handle signal: the element reference must be re-acquired, not retried as-is.
Example fix
// before act(target: "uid-42", action: "click") // page navigated; uid map stale // after snapshot() // refreshes uid -> BackendDOMNodeID act(target: "<new-uid>", action: "click")
Defensive patterns
Strategy: validation
Validate before calling
// Go: only attempt box-dependent actions on targets resolved from a live snapshot
func hasBackendNode(t Target) bool {
return t.BackendDOMNodeID > 0
} Type guard
func actionableTarget(t Target) (Target, bool) {
return t, t.BackendDOMNodeID > 0
} Prevention
- Re-snapshot after any navigation before issuing geometry-dependent actions.
- Never construct Target values by hand; take them from the driver's snapshot uid map.
- Treat BackendDOMNodeID == 0 as 'stale handle — re-acquire', not as retryable.
When it happens
Trigger: Calling an action or eval path that needs element geometry (click point calculation, bounding-box checks) with a Target struct whose BackendDOMNodeID was never populated — e.g. a uid target built from stale snapshot metadata after a page navigation, or a hand-constructed Target.
Common situations: Acting on a uid from an old snapshot after the page changed; race between snapshot and act; recovery metadata decoded from an expired handle.
Related errors
- resolve node returned no object
- select: missing option
- box model has no quad
- browser function threw
- browser returned no result object
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/c03da071330aa43c.
Report an issue: GitHub.