{"record":{"id":"24b1954559d08393","repo":"grafana/k6","slug":"unexpected-end-of-selector-while-parsing-selector","errorCode":null,"errorMessage":"Unexpected end of selector while parsing selector `${selector}`","messagePattern":"Unexpected end of selector while parsing selector `(.+?)`","errorType":"exception","errorClass":"InvalidSelectorError","httpStatus":null,"severity":"error","filePath":"internal/js/modules/k6/browser/common/js/injected_script.js","lineNumber":989,"sourceCode":"\n// packages/playwright-core/src/utils/isomorphic/cssParser.ts\nvar InvalidSelectorError = class extends Error {\n};\n\n// packages/playwright-core/src/utils/isomorphic/selectorParser.ts\nfunction parseAttributeSelector(selector, allowUnquotedStrings) {\n  let wp = 0;\n  let EOL = selector.length === 0;\n  const next = () => selector[wp] || \"\";\n  const eat1 = () => {\n    const result2 = next();\n    ++wp;\n    EOL = wp >= selector.length;\n    return result2;\n  };\n  const syntaxError = (stage) => {\n    if (EOL)\n      throw new InvalidSelectorError(`Unexpected end of selector while parsing selector \\`${selector}\\``);\n    throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - unexpected symbol \"${next()}\" at position ${wp}` + (stage ? \" during \" + stage : \"\"));\n  };\n  function skipSpaces() {\n    while (!EOL && /\\s/.test(next()))\n      eat1();\n  }\n  function isCSSNameChar(char) {\n    return char >= \"\\x80\" || char >= \"0\" && char <= \"9\" || char >= \"A\" && char <= \"Z\" || char >= \"a\" && char <= \"z\" || char >= \"0\" && char <= \"9\" || char === \"_\" || char === \"-\";\n  }\n  function readIdentifier() {\n    let result2 = \"\";\n    skipSpaces();\n    while (!EOL && isCSSNameChar(next()))\n      result2 += eat1();\n    return result2;\n  }\n  function readQuotedString(quote) {\n    let result2 = eat1();","sourceCodeStart":971,"sourceCodeEnd":1007,"githubUrl":"https://github.com/grafana/k6/blob/93accf6570dcd306ca5e99cc44c393ee3797761b/internal/js/modules/k6/browser/common/js/injected_script.js#L971-L1007","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nexecution.vu.meta.user = { id: 42, plan: 'pro' }; // TypeError: only String, Boolean and Number accepted\n\n// after\nexecution.vu.meta.userId = 42;\nexecution.vu.meta.plan = 'pro';\n// or, if structure must be kept:\nexecution.vu.meta.user = JSON.stringify({ id: 42, plan: 'pro' });","handlingStrategy":"type-guard","validationCode":"const META_TYPES = new Set(['string', 'number', 'boolean']);\n\nfunction safeSetMeta(key, value) {\n  if (!META_TYPES.has(typeof value)) {\n    throw new Error(\n      `metadata '${key}' must be string, number or boolean, got ${typeof value}`\n    );\n  }\n  execution.vu.meta[key] = value;\n}","typeGuard":"const isMetaValue = (v) =>\n  typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';","tryCatchPattern":"try {\n  execution.vu.meta[key] = value;\n} catch (e) {\n  if (e instanceof TypeError && /metric metadata/.test(e.message)) {\n    execution.vu.meta[key] = JSON.stringify(value); // or skip/log\n  } else {\n    throw e;\n  }\n}","preventionTips":["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"],"tags":["metrics","metadata","execution-module","type-error","javascript"],"backgroundTag":null,"analyzedSha":"93accf6570dcd306ca5e99cc44c393ee3797761b","analyzedAt":"2026-08-15T21:23:27.118Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}