{"record":{"id":"21184e318b0bc5cf","repo":"microsoft/playwright","slug":"error-while-parsing-selector-selector-canno-21184e","errorCode":null,"errorMessage":"Error while parsing selector `${selector}` - cannot use ${operator} in attribute with non-string matching value - ${value}","messagePattern":"Error while parsing selector `(.+?)` - cannot use (.+?) in attribute with non-string matching value - (.+?)","errorType":"exception","errorClass":"InvalidSelectorError","httpStatus":null,"severity":"error","filePath":"packages/isomorphic/selectorParser.ts","lineNumber":448,"sourceCode":"      if (value === 'true') {\n        value = true;\n      } else if (value === 'false') {\n        value = false;\n      } else {\n        if (!allowUnquotedStrings) {\n          value = +value;\n          if (Number.isNaN(value))\n            syntaxError('parsing attribute value');\n        }\n      }\n    }\n    skipSpaces();\n    if (next() !== ']')\n      syntaxError('parsing attribute value');\n\n    eat1();\n    if (operator !== '=' && typeof value !== 'string')\n      throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - cannot use ${operator} in attribute with non-string matching value - ${value}`);\n    return { name: jsonPath.join('.'), jsonPath, op: operator, value, caseSensitive };\n  }\n\n  const result: AttributeSelector = {\n    name: '',\n    attributes: [],\n  };\n  result.name = readIdentifier();\n  skipSpaces();\n  while (next() === '[') {\n    result.attributes.push(readAttribute());\n    skipSpaces();\n  }\n  if (!EOL)\n    syntaxError(undefined);\n  if (!result.name && !result.attributes.length)\n    throw new InvalidSelectorError(`Error while parsing selector \\`${selector}\\` - selector cannot be empty`);\n  return result;","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/isomorphic/selectorParser.ts#L430-L466","documentation":"Thrown when a non-= operator (*=, ^=, $=, |=, ~=) is paired with a non-string value (number or boolean). Substring/prefix/suffix operators only make sense for strings, so the parser rejects unquoted numeric/boolean operands. Values parsed as `true`/`false` become booleans; others become numbers via `+value` when unquoted strings are disallowed.","triggerScenarios":"Writing `page.locator('[data-index*=42]')`, `[count^=true]`, or any `[attr OP <number|true|false>]` where OP is a substring-style operator. Only happens when allowUnquotedStrings is false (strict parse path).","commonSituations":"Treating a numeric attribute as text without quotes; using a boolean keyword (`true`/`false`) with a substring operator; data-driven selectors that interpolate a numeric ID with `*=`.","solutions":["Quote the value so it is parsed as a string: `[data-index*=\"42\"]`.","Use `=` if you want exact numeric/boolean matching.","Coerce the dynamic value to a string before interpolating: `String(value)`."],"exampleFix":"// before\npage.locator(`[data-id*=${dynamicId}]`);  // numeric id -> rejected\n\n// after\npage.locator(`[data-id*=\"${String(dynamicId)}\"]`);","handlingStrategy":"validation","validationCode":"function assertSubstringOpValueIsString(sel: string) {\n  const m = sel.match(/\\[([^[\\]]+?)([*^$|~])=(true|false|-?\\d+(?:\\.\\d+)?)\\]/);\n  if (m) throw new Error(`Operator ${m[2]}= requires a quoted string, got ${m[3]}`);\n}\nassertSubstringOpValueIsString(selector);","typeGuard":"function substringOpValueIsQuoted(sel: string): boolean {\n  return !/\\[[^[\\]]+?[*^$|~]=(true|false|-?\\d)/.test(sel);\n}","tryCatchPattern":"try {\n  await page.locator(sel).click();\n} catch (e) {\n  if (/cannot use .* in attribute with non-string/.test(e.message)) {\n    sel = sel.replace(/(\\[\\w+[*^$|~]=)(-?\\d+|true|false)(\\])/, '$1\"$2\"$3');\n  }\n  throw e;\n}","preventionTips":["Quote dynamic values interpolated into substring operators.","Coerce IDs to strings before interpolation.","Prefer `=` for numeric/boolean exact matches."],"tags":["selector","parsing","invalid-selector","types"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}