grafana/k6 · error · InvalidSelectorError
Unexpected end of selector while parsing selector `${selecto
Error message
Unexpected end of selector while parsing selector `${selector}` What it means
Raised as a JavaScript TypeError when a script assigns a non-primitive value to a metadata key through the execution module's dynamic metadata object (execution.vu.meta). The Set method at internal/js/modules/k6/execution/execution.go:428 delegates to common.ApplyCustomUserMetadata (js/common/tags.go:60), which accepts only reflect.String, Bool, Int64 and Float64 kinds; anything else (objects, arrays, null, undefined, BigInt, functions) returns this error, which Set re-raises via runtime.NewTypeError. Note the value is also stringified on success (val.String()), the same restriction that applies to vu.tags.
Source
Thrown at internal/js/modules/k6/browser/common/js/injected_script.js:989
// packages/playwright-core/src/utils/isomorphic/cssParser.ts
var InvalidSelectorError = class extends Error {
};
// packages/playwright-core/src/utils/isomorphic/selectorParser.ts
function parseAttributeSelector(selector, allowUnquotedStrings) {
let wp = 0;
let EOL = selector.length === 0;
const next = () => selector[wp] || "";
const eat1 = () => {
const result2 = next();
++wp;
EOL = wp >= selector.length;
return result2;
};
const syntaxError = (stage) => {
if (EOL)
throw new InvalidSelectorError(`Unexpected end of selector while parsing selector \`${selector}\``);
throw new InvalidSelectorError(`Error while parsing selector \`${selector}\` - unexpected symbol "${next()}" at position ${wp}` + (stage ? " during " + stage : ""));
};
function skipSpaces() {
while (!EOL && /\s/.test(next()))
eat1();
}
function isCSSNameChar(char) {
return char >= "\x80" || char >= "0" && char <= "9" || char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char >= "0" && char <= "9" || char === "_" || char === "-";
}
function readIdentifier() {
let result2 = "";
skipSpaces();
while (!EOL && isCSSNameChar(next()))
result2 += eat1();
return result2;
}
function readQuotedString(quote) {
let result2 = eat1();View on GitHub (pinned to 93accf6570)
Solutions
- Assign only string, number, or boolean values: `execution.vu.meta.userId = 42;` or `execution.vu.meta.plan = 'pro';`
- Serialize complex data first: `execution.vu.meta.payload = JSON.stringify(obj);`
- If the value may be null/undefined, default it: `execution.vu.meta.k = v ?? 'n/a';`
- Remove a key with `delete execution.vu.meta.mykey;` instead of assigning null
- Remember values are stored as their string representation; read them back as strings, not as the original type
Example fix
// before
execution.vu.meta.user = { id: 42, plan: 'pro' }; // TypeError: only String, Boolean and Number accepted
// after
execution.vu.meta.userId = 42;
execution.vu.meta.plan = 'pro';
// or, if structure must be kept:
execution.vu.meta.user = JSON.stringify({ id: 42, plan: 'pro' }); Defensive patterns
Strategy: type-guard
Validate before calling
const META_TYPES = new Set(['string', 'number', 'boolean']);
function safeSetMeta(key, value) {
if (!META_TYPES.has(typeof value)) {
throw new Error(
`metadata '${key}' must be string, number or boolean, got ${typeof value}`
);
}
execution.vu.meta[key] = value;
} Type guard
const isMetaValue = (v) => typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';
Try / catch
try {
execution.vu.meta[key] = value;
} catch (e) {
if (e instanceof TypeError && /metric metadata/.test(e.message)) {
execution.vu.meta[key] = JSON.stringify(value); // or skip/log
} else {
throw e;
}
} Prevention
- Treat vu.meta and vu.tags as string/number/boolean maps only; never assign objects or arrays
- JSON.stringify structured values before storing them as metadata
- Default nullable sources: `execution.vu.meta.k = envVal ?? 'unknown'`
- Centralize metadata writes in one helper that type-checks, instead of scattering assignments across the script
When it happens
Trigger: Executing `execution.vu.meta['mykey'] = value` inside a script where value is an object, array, null, undefined, a function, or a BigInt. ExportType() returning nil (null/undefined) falls to reflect.Invalid and hits the default branch. Passing a variable read from an environment (string is fine) vs. parsed JSON (`JSON.parse(envVar)` yields objects/numbers) commonly trips it, as does reusing an options object as metadata.
Common situations: Scripts migrating from tags to metadata while assuming structured values are allowed; passing iteration data such as `{userId: 1}` instead of scalar values; setting metadata from untyped sources like environment variables parsed with JSON.parse; copying an options object (exec, env, tags) into vu.meta.
Related errors
- Error while parsing selector `${selector}`: ${e.message}
- Error while parsing selector `${selector}` - cannot use ${op
- must be an object with key-value pairs
- metrics must be declared in the init context
- invalid metadata param: %w
AI-assisted analysis of grafana/k6@93accf6570 (2026-08-15).
Data as JSON: /api/errors/24b1954559d08393.
Report an issue: GitHub.