{"record":{"id":"76be887420b95e63","repo":"tailwindlabs/tailwindcss","slug":"unterminated-string-input-slice-startidx-i-1","errorCode":null,"errorMessage":"Unterminated string: ${input.slice(startIdx, i + 1) + String.fromCharCode(quoteChar)}","messagePattern":"Unterminated string: (.+?)","errorType":"exception","errorClass":"CssSyntaxError","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/css-parser.ts","lineNumber":689,"sourceCode":"      return i\n    }\n\n    // End of the line without ending the string but with a `;` at the end.\n    //\n    // E.g.:\n    //\n    // ```css\n    // .foo {\n    //   content: \"This is a string with a;\n    //                                    ^ Missing \"\n    // }\n    // ```\n    else if (\n      peekChar === SEMICOLON &&\n      (input.charCodeAt(i + 1) === LINE_BREAK ||\n        (input.charCodeAt(i + 1) === CARRIAGE_RETURN && input.charCodeAt(i + 2) === LINE_BREAK))\n    ) {\n      throw new CssSyntaxError(\n        `Unterminated string: ${input.slice(startIdx, i + 1) + String.fromCharCode(quoteChar)}`,\n        source ? [source, startIdx, i + 1] : null,\n      )\n    }\n\n    // End of the line without ending the string.\n    //\n    // E.g.:\n    //\n    // ```css\n    // .foo {\n    //   content: \"This is a string with a\n    //                                    ^ Missing \"\n    // }\n    // ```\n    else if (\n      peekChar === LINE_BREAK ||\n      (peekChar === CARRIAGE_RETURN && input.charCodeAt(i + 1) === LINE_BREAK)","sourceCodeStart":671,"sourceCodeEnd":707,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/css-parser.ts#L671-L707","documentation":"Thrown by the string scanner when, inside a quoted string, it sees a semicolon whose next character is a line break (or CRLF). That pattern means the string was never closed before the declaration terminator and newline — i.e. an unterminated string that the parser cannot recover gracefully. The message reconstructs the partial string from `startIdx` to the current position and appends the quote character that was expected.","triggerScenarios":"Writing `.x { content: \"hello; }` where the `;` is inside the quotes but the closing quote is missing, followed by a newline. The scanner treats `\"…;<newline>` as evidence the string spilled past the declaration boundary.","commonSituations":"Forgetting the closing quote in `content:`; multi-line content strings authored without proper escaping; copy-paste that drops the trailing quote.","solutions":["Close the string with the matching quote, e.g. `content: \"hello\";`.","For multi-line content, escape newlines or use a backslash continuation as CSS allows.","Use single quotes consistently to avoid confusion with apostrophes in the content."],"exampleFix":"/* before */\n.x { content: \"hello;\n}\n/* after */\n.x { content: \"hello\"; }","handlingStrategy":"validation","validationCode":"// Detect unterminated strings terminated by `;<newline>`\nfunction findUnterminatedStrings(css: string): string[] {\n  const bad: string[] = [];\n  const re = /([\"'])((?:[^\"'\\n])*);[ \\t]*\\n/g;\n  let m;\n  while ((m = re.exec(css))) {\n    if (!m[2].includes(m[1])) bad.push(m[0]);\n  }\n  return bad;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const ast = CSS.parse(input);\n} catch (e) {\n  if (e instanceof CssSyntaxError && e.message.startsWith('Unterminated string')) {\n    // message includes the partial string and expected quote\n  } else throw e;\n}","preventionTips":["Always close quoted strings with the matching quote.","Use a CSS-aware editor that flags unterminated strings.","For content: values, prefer single quotes if the text contains apostrophes."],"tags":["tailwind-v4","css-parser","string","unterminated","syntax-error"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}