{"record":{"id":"656ebae411898b44","repo":"tailwindlabs/tailwindcss","slug":"missing-closing-at-parent-selector","errorCode":null,"errorMessage":"Missing closing } at ${parent.selector}","messagePattern":"Missing closing \\} at (.+?)","errorType":"exception","errorClass":"CssSyntaxError","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/css-parser.ts","lineNumber":575,"sourceCode":"  // means that we have an at-rule that is not terminated with a semicolon at\n  // the end of the input.\n  if (buffer.charCodeAt(0) === AT_SIGN) {\n    let node = parseAtRule(buffer)\n\n    // Track the source location for source maps\n    if (source) {\n      node.src = [source, bufferStart, input.length]\n      node.dst = [source, bufferStart, input.length]\n    }\n\n    ast.push(node)\n  }\n\n  // When we are done parsing then everything should be balanced. If we still\n  // have a leftover `parent`, then it means that we have an unterminated block.\n  if (closingBracketStack.length > 0 && parent) {\n    if (parent.kind === 'rule') {\n      throw new CssSyntaxError(\n        `Missing closing } at ${parent.selector}`,\n        parent.src ? [parent.src[0], parent.src[1], parent.src[1]] : null,\n      )\n    }\n\n    if (parent.kind === 'at-rule') {\n      throw new CssSyntaxError(\n        `Missing closing } at ${parent.name} ${parent.params}`,\n        parent.src ? [parent.src[0], parent.src[1], parent.src[1]] : null,\n      )\n    }\n  }\n\n  if (licenseComments.length > 0) {\n    return (licenseComments as AstNode[]).concat(ast)\n  }\n\n  return ast","sourceCodeStart":557,"sourceCodeEnd":593,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/css-parser.ts#L557-L593","documentation":"Thrown at end-of-input when the bracket stack is still non-empty (`closingBracketStack.length > 0`) and the unclosed parent node is a style `rule`. The parser reached the end of the file with at least one `{` that was never matched by a `}`. The error message embeds the rule's selector and the source position is derived from the rule's own `src` so users can jump to where the block opened.","triggerScenarios":"A rule missing its closing `}`, e.g. `.x { color: red;` at EOF; nested rules where an inner block was never closed; a truncated stylesheet. The branch keys on `parent.kind === 'rule'`.","commonSituations":"Author forgot the final `}`; file truncated during save/transfer; broken generated CSS; editor auto-close disabled.","solutions":["Add the missing `}` for the rule named in the message.","Use brace-matching in your editor to locate the unclosed block.","Format the file with a CSS formatter to surface the imbalance.","If generated, fix the template to always emit a closing brace."],"exampleFix":"/* before */\n.x {\n  color: red;\n/* after */\n.x {\n  color: red;\n}","handlingStrategy":"validation","validationCode":"function findUnclosedBlocks(css: string): boolean {\n  let depth = 0;\n  for (const ch of css) {\n    if (ch === '{') depth++;\n    else if (ch === '}') depth--;\n  }\n  return depth !== 0; // true => unclosed blocks remain\n}","typeGuard":null,"tryCatchPattern":"try {\n  const ast = CSS.parse(input);\n} catch (e) {\n  if (e instanceof CssSyntaxError && e.message.startsWith('Missing closing }')) {\n    // message names the rule selector; add its closing brace\n  } else throw e;\n}","preventionTips":["Always close every rule block with }.","Use brace matching and a CSS formatter.","For large files, fold blocks to verify closure."],"tags":["tailwind-v4","css-parser","unclosed-block","syntax-error"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}