grafana/k6 · error
options[%v]: expected string, got %T
Error message
options[%v]: expected string, got %T
What it means
Thrown by extractSelectOptionFromMap when a selectOption descriptor object has a value or label key that is not a string. The value and label fields must be strings (index must be an integer); anything else rejects with 'options[<key>]: expected string, got <type>' (e.g. options[value]: expected string, got float64), wrapped by the mapping as 'parsing select option values: ...'.
Source
Thrown at internal/js/modules/k6/browser/browser/mapping.go:140
*labelOpt.Label = t.(string) //nolint:forcetypeassert
opts = append(opts, &valOpt, &labelOpt)
default:
return nil, fmt.Errorf("options: unsupported type %T", values)
}
return opts, nil
}
func extractSelectOptionFromMap(v map[string]any) (*common.SelectOption, error) {
opt := &common.SelectOption{}
for k, raw := range v {
switch k {
case "value":
opt.Value = new(string)
v, ok := raw.(string)
if !ok {
return nil, fmt.Errorf("options[%v]: expected string, got %T", k, raw)
}
*opt.Value = v
case "label":
opt.Label = new(string)
v, ok := raw.(string)
if !ok {
return nil, fmt.Errorf("options[%v]: expected string, got %T", k, raw)
}
*opt.Label = v
case "index":
opt.Index = new(int64)
switch raw := raw.(type) {
case int:
*opt.Index = int64(raw)
case int64:View on GitHub (pinned to 93accf6570)
Solutions
- Stringify value and label: selectOption({ value: String(id) })
- Use { index: n } (number) for positional selection, not { value: n }
- Drop null/undefined keys from descriptors instead of passing them
- Validate descriptor objects against { value?: string, label?: string, index?: number } before the call
Example fix
// before
await page.locator('select').selectOption({ value: 42 });
// after
await page.locator('select').selectOption({ value: '42' }); // or { index: 42 } Defensive patterns
Strategy: type-guard
Validate before calling
function normalizeDescriptor(d) {
const o = {};
if (d.value !== undefined && d.value !== null) {
if (typeof d.value !== 'string') throw new TypeError(`descriptor value must be a string, got ${typeof d.value}`);
o.value = d.value;
}
if (d.label !== undefined && d.label !== null) {
if (typeof d.label !== 'string') throw new TypeError(`descriptor label must be a string, got ${typeof d.label}`);
o.label = d.label;
}
if (d.index !== undefined) o.index = Number(d.index);
return o;
} Type guard
function isSelectDescriptor(v) {
if (typeof v !== 'object' || v === null || Array.isArray(v)) return false;
return (v.value === undefined || typeof v.value === 'string') &&
(v.label === undefined || typeof v.label === 'string') &&
(v.index === undefined || typeof v.index === 'number');
} Try / catch
try {
await locator.selectOption(values, opts);
} catch (e) {
if (/options\[.*\]: expected string/.test(String(e.message))) {
throw new Error(`Descriptor value/label must be strings; use { index: n } for numbers: ${e.message}`);
}
throw e;
} Prevention
- Stringify value and label fields coming from JSON or APIs
- Reserve numbers for the index key only
- Drop undefined/null keys from descriptors instead of passing them through
When it happens
Trigger: selectOption({ value: 2 }) — numeric value instead of string; selectOption({ label: null }); selectOption([{ value: ['a'] }]) — array-valued descriptor field; only index may be numeric.
Common situations: JSON fixtures where option values are numbers; sloppy destructuring leaving undefined/null in descriptors; mixing index and value conventions in one descriptor with wrong types.
Related errors
- parsing select option values: %w
- options: expected array, got %T
- options: expected string or object, got %T
- options: expected object, got %T
- options: unsupported type %T
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/04f010d0bc7f37cf.
Report an issue: GitHub.