{"record":{"id":"3bbb694591cfe4cf","repo":"microsoft/playwright","slug":"invalid-character-the-input-contains-u-0000","errorCode":null,"errorMessage":"Invalid character: the input contains U+0000.","messagePattern":"Invalid character: the input contains U\\+0000\\.","errorType":"exception","errorClass":"InvalidCharacterError","httpStatus":null,"severity":"error","filePath":"packages/isomorphic/cssTokenizer.ts","lineNumber":899,"sourceCode":"    const source = this.repr;\n    let unit = escapeIdent(this.unit);\n    if (unit[0].toLowerCase() === 'e' && (unit[1] === '-' || between(unit.charCodeAt(1), 0x30, 0x39))) {\n      // Unit is ambiguous with scinot\n      // Remove the leading \"e\", replace with escape.\n      unit = '\\\\65 ' + unit.slice(1, unit.length);\n    }\n    return source + unit;\n  }\n}\n\nfunction escapeIdent(string: string) {\n  string = '' + string;\n  let result = '';\n  const firstcode = string.charCodeAt(0);\n  for (let i = 0; i < string.length; i++) {\n    const code = string.charCodeAt(i);\n    if (code === 0x0)\n      throw new InvalidCharacterError('Invalid character: the input contains U+0000.');\n\n    if (\n      between(code, 0x1, 0x1f) || code === 0x7f ||\n      (i === 0 && between(code, 0x30, 0x39)) ||\n      (i === 1 && between(code, 0x30, 0x39) && firstcode === 0x2d)\n    )\n      result += '\\\\' + code.toString(16) + ' ';\n    else if (\n      code >= 0x80 ||\n      code === 0x2d ||\n      code === 0x5f ||\n      between(code, 0x30, 0x39) ||\n      between(code, 0x41, 0x5a) ||\n      between(code, 0x61, 0x7a)\n    )\n      result += string[i];\n    else\n      result += '\\\\' + string[i];","sourceCodeStart":881,"sourceCodeEnd":917,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/isomorphic/cssTokenizer.ts#L881-L917","documentation":"escapeIdent() throws InvalidCharacterError when the string it is asked to escape contains a NUL character (U+0000). CSS identifiers cannot represent U+0000 even escaped, so the algorithm from CSSOM CSS.escape aborts. escapeIdent is used internally when serializing CSS token identifiers (element names, class names, idents in pseudo-classes).","triggerScenarios":"Any API path that builds a CSS identifier from a runtime string containing '\\0', '\\u0000', or a raw NUL byte: text/role/attribute matching where the value reaches the CSS serializer, or constructing class/tag selectors from data containing NUL.","commonSituations":"Data scraped from a page or read from a file/database containing NUL bytes (common in legacy/CRLF/binary-corrupted text); test fixtures with embedded control characters; passing Buffer.toString() of binary data into a selector builder.","solutions":["Strip or replace NUL bytes before passing the string into selector-building code: str.replace(/\\0/g, '').","Validate input at the boundary: if (str.includes('\\u0000')) throw new TypeError('NUL not allowed').","Use a locator API that treats the value as opaque data (getByText/getByRole with a string) rather than embedding it into CSS syntax."],"exampleFix":"// before\nconst name = rawWithNul; // contains '\\u0000'\nawait page.locator(`.${name}`).click();\n\n// after\nconst clean = name.replace(/\\u0000/g, '');\nawait page.getByText(clean).click();","handlingStrategy":"validation","validationCode":"function hasNoNul(s: string): boolean { return !s.includes('\\u0000'); }","typeGuard":"function isNulFreeString(s: unknown): s is string { return typeof s === 'string' && !s.includes('\\u0000'); }","tryCatchPattern":"try { await page.locator(buildSelector(value)).click(); }\ncatch (e) { if (/U\\+0000/.test(e.message)) { value = value.replace(/\\u0000/g, ''); } else throw e; }","preventionTips":["Sanitize scraped/external text to strip NUL at ingestion.","Use data-based locators (getByText/getByRole with a string) instead of embedding values into CSS identifiers.","Add boundary validation rejecting control chars before selector construction."],"tags":["css","tokenizer","escaping","invalid-character","user-input"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}