JuliusBrussee/caveman · warning
option not found
Error message
option not found
What it means
SanitizeAttributes in shared/platform/telemetry/span.go rejects an attribute map once more than MaxAttributes (128) keys survive the allowlist filter. Telemetry pipelines cap attribute count so spans stay bounded and downstream exporters do not reject or drop oversized records. The function fails closed: the error tells the caller to trim the map rather than silently truncating it.
Source
Thrown at browse/cdp.go:207
})); err != nil {
return ActionResult{OK: false, Settled: false}, err
}
return dispatchedAction(), nil
case "select":
if err := d.scrollIntoView(runCtx, target); err != nil {
return ActionResult{OK: false, Settled: false}, err
}
if _, _, err := d.waitActionable(runCtx, target); err != nil {
return ActionResult{OK: false, Settled: false}, err
}
option := req.Option
if option == "" {
option = req.Text
}
if option == "" {
return ActionResult{OK: false, Settled: false}, errors.New("select: missing option")
}
if err := d.callOnNode(runCtx, target, fmt.Sprintf(`function(){ const wanted = %s; const options = Array.from(this.options || []); const match = options.find(o => o.value === wanted || o.label === wanted || o.textContent.trim() === wanted); if (!match) { throw new Error("option not found"); } this.value = match.value; this.dispatchEvent(new Event("input", {bubbles:true})); this.dispatchEvent(new Event("change", {bubbles:true})); return true; }`, jsString(option))); err != nil {
return ActionResult{OK: false, Settled: false}, err
}
return dispatchedAction(), nil
case "scroll":
if err := d.scrollIntoView(runCtx, target); err != nil {
return ActionResult{OK: false, Settled: false}, err
}
if _, _, err := d.waitActionable(runCtx, target); err != nil {
return ActionResult{OK: false, Settled: false}, err
}
return dispatchedAction(), nil
default:
return ActionResult{OK: false, Settled: false}, fmt.Errorf("unknown action: %s", req.Action)
}
}
func dispatchedAction() ActionResult {
// CDP acknowledged dispatch, but asynchronous application state may still beView on GitHub (pinned to 27d5a3981a)
Solutions
- Count allowlisted keys before building the span: if more than 128 survive, keep only the highest-priority ones (trace id, route, status).
- Hoist static/repeated attributes into a shared resource or logger configuration instead of per-span attributes.
- Raise MaxAttributes in shared/platform/telemetry/span.go:39 only if your exporter supports it, and re-run telemetry tests.
Example fix
// before
attrs := map[string]string{}
for k, v := range requestHeaders {
attrs[k] = v // unbounded growth
}
span := tracer.Start(ctx, attrs)
// after
attrs := map[string]string{}
for k, v := range requestHeaders {
if len(attrs) >= telemetry.MaxAttributes {
break
}
attrs[k] = v
}
span := tracer.Start(ctx, attrs) Defensive patterns
Strategy: validation
Validate before calling
func countAllowedAttrs(attrs map[string]string) int {
n := 0
for k := range attrs {
if telemetry.AttributeAllowed(k) {
n++
}
}
return n
}
// before span creation:
if countAllowedAttrs(attrs) > telemetry.MaxAttributes {
attrs = pruneAttrs(attrs, telemetry.MaxAttributes) // keep priority keys
} Type guard
func attrsWithinKeyCount(attrs map[string]string) bool {
return countAllowedAttrs(attrs) <= telemetry.MaxAttributes
} Prevention
- Build span attributes from a fixed, reviewed set of keys instead of copying arbitrary maps.
- Run telemetry unit tests that assert attribute count stays under 128 for every instrumented call path.
- Log-and-drop instead of propagate when SanitizeAttributes errors: sanitization failures should degrade telemetry, not the request.
When it happens
Trigger: Calling SanitizeAttributes(attrs) (or a span-recording API that routes through it) with a map where more than 128 distinct keys pass AttributeAllowed. Only allowlisted keys count toward the limit, so a large map of disallowed keys does not trigger it, but 129+ allowed keys does.
Common situations: Attaching per-request dimensions dynamically (user id, trace flags, feature flags) until the map grows past 128; bulk-forwarding upstream headers or labels into span attributes; a loop that accumulates attributes across retries without resetting the map.
Related errors
- cave_harness_adapter_version_invalid
- cave_harness_upstream_version_invalid
- cave_harness_artifact_digest_invalid
- caveman agent: subagent maxInputChars must be a positive int
- cave_${field}_invalid
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/168a2559bd719ab0.
Report an issue: GitHub.