grafana/k6 · error

unknown option: %s

Error message

unknown option: %s

What it means

Inside parseWaitForEventOptions, the options-object branch iterates keys and only `predicate` (must be callable) and `timeout` (number, coerced to milliseconds) are recognized; every other key hits the default branch at internal/js/modules/k6/browser/browser/browser_context_mapping.go:220 and returns 'unknown option: <key>'. Users see it wrapped by the outer 'parsing wait for event options' message.

Source

Thrown at internal/js/modules/k6/browser/browser/browser_context_mapping.go:220

	}
	var isCallable bool
	w.PredicateFn, isCallable = sobek.AssertFunction(optsOrPredicate)
	if isCallable {
		return w, nil
	}

	opts := optsOrPredicate.ToObject(rt)
	for _, k := range opts.Keys() {
		switch k {
		case "predicate":
			w.PredicateFn, isCallable = sobek.AssertFunction(opts.Get(k))
			if !isCallable {
				return nil, errors.New("predicate function is not callable")
			}
		case "timeout":
			w.Timeout = time.Duration(opts.Get(k).ToInteger()) * time.Millisecond
		default:
			return nil, fmt.Errorf("unknown option: %s", k)
		}
	}

	return w, nil
}

View on GitHub (pinned to 93accf6570)

Solutions

  1. Restrict the options object to exactly { predicate?, timeout? }
  2. Set a default timeout via browser/context options (setDefaultTimeout) instead of adding non-standard keys
  3. For a predicate-only use, pass the function directly as the second argument

Example fix

// before: extra Playwright-style property
await context.waitForEvent('console', {
  predicate: (msg) => msg.type() === 'error',
  timeout: 1000,
  signal: ctrl.signal, // unknown option: signal
});

// after: only supported keys
await context.waitForEvent('console', {
  predicate: (msg) => msg.type() === 'error',
  timeout: 1000,
});
Defensive patterns

Strategy: validation

Validate before calling

// strip unsupported keys before calling
const ALLOWED = new Set(['predicate', 'timeout']);
function sanitizeWaitForEventOpts(o) {
  if (o == null || typeof o === 'function') return o;
  return Object.fromEntries(Object.entries(o).filter(([k]) => ALLOWED.has(k)));
}
await context.waitForEvent('page', sanitizeWaitForEventOpts(opts));

Type guard

function isKnownWaitForEventKeySet(o) {
  if (typeof o !== 'object' || o === null) return false;
  return Object.keys(o).every((k) => k === 'predicate' || k === 'timeout');
}

Prevention

When it happens

Trigger: waitForEvent('console', { predicate: () => true, timeout: 1000, signal: abortCtrl.signal }); typos like { timeouts: 1000 } or { timeoutMs: 1000 }; passing a string as optsOrPredicate, which ToObject turns into index keys and reports 'unknown option: 0'.

Common situations: Copying Playwright's waitForEvent options (which tolerate extra fields) into k6; IDE autocompleting unrelated option names; leftover abort-signal or polling options.

Related errors


AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15). Data as JSON: /api/errors/2612d47be53a8477. Report an issue: GitHub.