{"record":{"id":"3abe2900df7fd576","repo":"tailwindlabs/tailwindcss","slug":"missing-opening","errorCode":null,"errorMessage":"Missing opening {","messagePattern":"Missing opening \\{","errorType":"exception","errorClass":"CssSyntaxError","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/css-parser.ts","lineNumber":427,"sourceCode":"      // nested nodes are done.\n      stack.push(parent)\n\n      // Make the current node the new parent, so that nested nodes can be\n      // attached to it.\n      parent = node\n\n      // Reset the state for the next node.\n      buffer = ''\n      node = null\n    }\n\n    // End of a block.\n    else if (\n      currentChar === CLOSE_CURLY &&\n      closingBracketStack[closingBracketStack.length - 1] !== ')'\n    ) {\n      if (closingBracketStack === '') {\n        throw new CssSyntaxError('Missing opening {', source ? [source, i, i] : null)\n      }\n\n      closingBracketStack = closingBracketStack.slice(0, -1)\n\n      // When we hit a `}` and `buffer` is filled in, then it means that we did\n      // not complete the previous node yet. This means that we hit a\n      // declaration without a `;` at the end.\n      if (buffer.length > 0) {\n        // This can happen for nested at-rules.\n        //\n        // E.g.:\n        //\n        // ```css\n        // @layer foo {\n        //   @tailwind utilities\n        //                      ^\n        // }\n        // ```","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/css-parser.ts#L409-L445","documentation":"Thrown when the parser encounters a closing curly brace `}` but the bracket stack (`closingBracketStack`) is empty — meaning there was no matching `{` opened. The check `closingBracketStack === ''` (empty string) fires before slicing the stack. The error is raised with source position `[source, i, i]` pointing at the offending `}`.","triggerScenarios":"An extra `}` in the stylesheet (more closers than openers); a `}` after a declaration that was not inside a rule; malformed nested CSS where a block was double-closed. The branch only triggers when the top of the bracket stack is not `)` (parens are tracked separately).","commonSituations":"Typing an extra `}`; deleting a selector but leaving its closer; broken generated CSS; copy-paste errors merging blocks.","solutions":["Count `{` and `}` braces in the offending file/region and remove the surplus `}`.","Use an editor with brace-matching to locate the unbalanced closer.","Run the CSS through a formatter/prettier to surface the mismatch.","If the input is generated, fix the template that emits the extra brace."],"exampleFix":"/* before */\n.x { color: red; }\n}\n/* after */\n.x { color: red; }","handlingStrategy":"validation","validationCode":"function bracesBalanced(css: string): boolean {\n  let depth = 0;\n  for (const ch of css) {\n    if (ch === '{') depth++;\n    else if (ch === '}') depth--;\n    if (depth < 0) return false;\n  }\n  return depth === 0;\n}\nif (!bracesBalanced(input)) throw new Error('Unbalanced curly braces');","typeGuard":null,"tryCatchPattern":"try {\n  const ast = CSS.parse(input);\n} catch (e) {\n  if (e instanceof CssSyntaxError && e.message === 'Missing opening {') {\n    // locate the extra } via the source coordinates\n  } else throw e;\n}","preventionTips":["Use an editor with brace matching.","Format CSS with prettier/stylelint to surface imbalance.","For generated CSS, unit-test brace balance."],"tags":["tailwind-v4","css-parser","bracket-mismatch","syntax-error"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}