apple/pkl · error · GenericParserError

wrongHeaders

wrongHeaders

Error message

{0} cannot have doc comments, annotations or modifiers.

What it means

Pkl's module parser rejects doc comments, annotations, or modifiers appearing between the module header clauses and the imports section. Imports must come directly after the module/amends/extends headers, before anything else; parserError("wrongHeaders", "Imports") fires when res already accumulated a doc comment, annotations, or modifiers by the time an import token is seen.

Source

Thrown at pkl-parser/src/main/java/org/pkl/parser/GenericParserImpl.java:74

    if (lookahead == Token.SHEBANG) {
      nodes.add(makeAffix(next()));
    }
    ff(nodes);

    var res = parseMemberHeader(children);

    if (isModuleDecl()) {
      nodes.add(parseModuleDecl(children));
      children.clear();
      res = new HeaderResult(false, false, false);
      ff(nodes);
    }

    // imports
    var imports = new ArrayList<Node>();
    while (lookahead == Token.IMPORT || lookahead == Token.IMPORT_STAR) {
      if (res.hasDocComment || res.hasAnnotations || res.hasModifiers) {
        throw parserError("wrongHeaders", "Imports");
      }
      var lastImport = parseImportDecl();
      imports.add(lastImport);
      // keep trailing affixes as part of the import
      while (lookahead.isAffix() && lastImport.span.isSameLine(spanLookahead)) {
        imports.add(makeAffix(next()));
      }
      if (!isImport()) break;
      ff(imports);
    }
    if (!imports.isEmpty()) {
      nodes.add(new Node(NodeType.IMPORT_LIST, imports));
      ff(nodes);
    }

    // entries
    if (res.hasDocComment || res.hasAnnotations || res.hasModifiers) {
      nodes.add(parseModuleMember(children));

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Move all import statements to immediately after the module/amends/extends header, before any doc comment, annotation, or modifier lines.
  2. Attach the doc comment/annotations to the actual declaration they document (a class, property, or the module itself) rather than leaving them above imports.
  3. Remove modifiers that aren't valid on imports; imports accept no modifiers in Pkl.

Example fix

// before
@Deprecated
import "lib.pkl"
module my.mod
// after
module my.mod
import "lib.pkl"

@Deprecated
foo { ... }
Defensive patterns

Strategy: validation

Validate before calling

// lint rule: imports must appear before any doc comment/annotation/modifier line after the header
const bad = /(\/\/\/|@[A-Za-z_]|\b(open|abstract|sealed|hidden)\b)[^\n]*\n\s*(import\s)/;
if (bad.test(pklSource)) throw new Error("Move imports above doc comments/annotations/modifiers");

Prevention

When it happens

Trigger: A .pkl module declares a doc comment (///), annotations (@...), or modifiers (e.g. `open`, `abstract`) and THEN writes `import ...` statements, e.g. `module x\n@Deprecated\nimport "a"` or `open module m\n/// doc\nimport "b"`.

Common situations: Reordering statements while refactoring (moving imports above/below annotations); auto-formatters or code generators emitting imports after annotations; developers assuming import placement is free-form like in Java.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/3a16126102758fff. Report an issue: GitHub.