tailwindlabs/tailwindcss · error · CssSyntaxError

Invalid custom property, expected a value

Error message

Invalid custom property, expected a value

What it means

Thrown by the CSS parser while scanning a custom property (a declaration whose name starts with `--`). After collecting the value up to the terminating `}` or end-of-input, it calls `parseDeclaration(buffer, colonIdx)`; if that returns null the declaration is unparseable (typically because the value is empty or malformed) and the parser raises a `CssSyntaxError` with source-location metadata. The message specifically flags custom properties because they have relaxed value rules — failing to parse one usually means the value is missing entirely.

Source

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

        // End of a block.
        else if (
          peekChar === CLOSE_PAREN ||
          peekChar === CLOSE_BRACKET ||
          peekChar === CLOSE_CURLY
        ) {
          if (
            closingBracketStack.length > 0 &&
            input[j] === closingBracketStack[closingBracketStack.length - 1]
          ) {
            closingBracketStack = closingBracketStack.slice(0, -1)
          }
        }
      }

      let declaration = parseDeclaration(buffer, colonIdx)
      if (!declaration) {
        throw new CssSyntaxError(
          `Invalid custom property, expected a value`,
          source ? [source, start, i] : null,
        )
      }

      if (source) {
        declaration.src = [source, start, i]
        declaration.dst = [source, start, i]
      }

      if (parent) {
        parent.nodes.push(declaration)
      } else {
        ast.push(declaration)
      }

      buffer = ''
    }

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Give the custom property a concrete value, e.g. `--my-var: #fff;`.
  2. If the value is intentionally empty/invalid, use a valid placeholder like `--my-var: initial;`.
  3. Terminate the declaration with a semicolon and ensure the value is non-empty before the closing brace.
  4. Check generated/templated CSS to confirm the value slot is populated.

Example fix

/* before */
.x {
  --brand-color:
}
/* after */
.x {
  --brand-color: #3b82f6;
}
Defensive patterns

Strategy: validation

Validate before calling

// Reject empty custom property values before sending CSS to Tailwind
function validateCustomProperties(css: string): string[] {
  const errors: string[] = [];
  for (const m of css.matchAll(/(--[\w-]+)\s*:\s*(?:;|\}|$)/gm)) {
    errors.push(`Empty value for custom property ${m[1]}`);
  }
  return errors;
}

Try / catch

try {
  const ast = CSS.parse(input);
} catch (e) {
  if (e instanceof CssSyntaxError && e.message.includes('Invalid custom property')) {
    // surface the source line, offer a fix
  } else throw e;
}

Prevention

When it happens

Trigger: Writing `--my-var: ;` with an empty value at the end of a block without a semicolon, or `--my-var:` followed immediately by `}`, or a custom property whose value consists only of a malformed token the declaration parser rejects. The branch is reached specifically for `--`-prefixed declarations (custom properties).

Common situations: Author error leaving a custom property value blank; a broken `@property` override; generated CSS that emits `--x:` with no value; minifier or preprocessor stripping a value.

Related errors


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