dianping/cat · error · SyntaxError

@charset not allowed here.

Error message

@charset not allowed here.

What it means

Thrown when `@charset` appears at a position in the stylesheet where it is illegal — it must be the very first statement (only `@charset` may precede it, nothing else). The parser's default branch first tries `_ruleset()`; if that fails and the token is `CHARSET_SYM`, it consumes the rule (so parsing can continue) and then throws `SyntaxError('@charset not allowed here.')` at the `@charset` token's position. In non-strict mode this is caught and fired as an 'error' event instead of aborting.

Source

Thrown at cat-home/src/main/webapp/assets/js/editor/worker-css.js:2061

                                    while(count){
                                        tokenStream.advance([Tokens.RBRACE]);
                                        count--;
                                    }

                                } else {
                                    throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol);
                                }
                                break;
                            case Tokens.S:
                                this._readWhitespace();
                                break;
                            default:
                                if(!this._ruleset()){
                                    switch(tt){
                                        case Tokens.CHARSET_SYM:
                                            token = tokenStream.LT(1);
                                            this._charset(false);
                                            throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol);
                                        case Tokens.IMPORT_SYM:
                                            token = tokenStream.LT(1);
                                            this._import(false);
                                            throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol);
                                        case Tokens.NAMESPACE_SYM:
                                            token = tokenStream.LT(1);
                                            this._namespace(false);
                                            throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol);
                                        default:
                                            tokenStream.get();  //get the last token
                                            this._unexpectedToken(tokenStream.token());
                                    }

                                }
                        }
                    } catch(ex) {
                        if (ex instanceof SyntaxError && !this.options.strict){
                            this.fire({

View on GitHub (pinned to e815e74d4c)

Solutions

  1. Move the single `@charset "utf-8";` to the absolute top of the file, before any rules, comments with rules, or `@import`.
  2. If you concatenate or inline CSS, strip all `@charset` statements except (optionally) one at the head of the output.
  3. Serve the stylesheet as UTF-8 with the right HTTP `Content-Type`/BOM and delete `@charset` entirely — it is rarely needed.
  4. Keep the parser in non-strict mode and surface the fired error event so users see the position instead of a thrown crash.

Example fix

/* before */
:root { --x: 1; }
@charset "utf-8";   /* @charset not allowed here. */

/* after */
@charset "utf-8";
:root { --x: 1; }
Defensive patterns

Strategy: validation

Validate before calling

function charsetOk(css) {
  var first = css.replace(/^(\s|\/\*[\s\S]*?\*\/\s*)*/, '');
  var count = (css.match(/@charset\b/g) || []).length;
  return count === 0 || (count === 1 && /^@charset/.test(first));
}

Try / catch

try {
  parser.parse(css);
} catch (ex) {
  if (/@charset not allowed/.test(ex.message)) { css = css.replace(/@charset[^;]+;?\s*/g, ''); parser.parse(css); return; }
  throw ex;
}

Prevention

When it happens

Trigger: `@charset "utf-8";` placed after any rule, selector block, `@import`, comment-with-rules, or anywhere other than byte-position 0 of the stylesheet; concatenating files where a later fragment contains its own `@charset`; feeding the parser a stylesheet fragment that retains an inner `@charset`.

Common situations: Build tools concatenating many CSS files without stripping their individual `@charset` lines; `@import` inlining that leaves the imported file's `@charset` mid-stream; developers pasting a boilerplate header below existing rules.

Related errors


AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14). Data as JSON: /api/errors/3eed6811ea2286a7. Report an issue: GitHub.