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 be

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Count allowlisted keys before building the span: if more than 128 survive, keep only the highest-priority ones (trace id, route, status).
  2. Hoist static/repeated attributes into a shared resource or logger configuration instead of per-span attributes.
  3. 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

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


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