tailwindlabs/tailwindcss · error · CssSyntaxError

Missing opening {

Error message

Missing opening {

What it means

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 `}`.

Source

Thrown at packages/tailwindcss/src/css-parser.ts:427

      // nested nodes are done.
      stack.push(parent)

      // Make the current node the new parent, so that nested nodes can be
      // attached to it.
      parent = node

      // Reset the state for the next node.
      buffer = ''
      node = null
    }

    // End of a block.
    else if (
      currentChar === CLOSE_CURLY &&
      closingBracketStack[closingBracketStack.length - 1] !== ')'
    ) {
      if (closingBracketStack === '') {
        throw new CssSyntaxError('Missing opening {', source ? [source, i, i] : null)
      }

      closingBracketStack = closingBracketStack.slice(0, -1)

      // When we hit a `}` and `buffer` is filled in, then it means that we did
      // not complete the previous node yet. This means that we hit a
      // declaration without a `;` at the end.
      if (buffer.length > 0) {
        // This can happen for nested at-rules.
        //
        // E.g.:
        //
        // ```css
        // @layer foo {
        //   @tailwind utilities
        //                      ^
        // }
        // ```

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Count `{` and `}` braces in the offending file/region and remove the surplus `}`.
  2. Use an editor with brace-matching to locate the unbalanced closer.
  3. Run the CSS through a formatter/prettier to surface the mismatch.
  4. If the input is generated, fix the template that emits the extra brace.

Example fix

/* before */
.x { color: red; }
}
/* after */
.x { color: red; }
Defensive patterns

Strategy: validation

Validate before calling

function bracesBalanced(css: string): boolean {
  let depth = 0;
  for (const ch of css) {
    if (ch === '{') depth++;
    else if (ch === '}') depth--;
    if (depth < 0) return false;
  }
  return depth === 0;
}
if (!bracesBalanced(input)) throw new Error('Unbalanced curly braces');

Try / catch

try {
  const ast = CSS.parse(input);
} catch (e) {
  if (e instanceof CssSyntaxError && e.message === 'Missing opening {') {
    // locate the extra } via the source coordinates
  } else throw e;
}

Prevention

When it happens

Trigger: 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).

Common situations: Typing an extra `}`; deleting a selector but leaving its closer; broken generated CSS; copy-paste errors merging blocks.

Related errors


AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12). Data as JSON: /api/errors/3abe2900df7fd576. Report an issue: GitHub.