apple/pkl · error

invalidObjectMemberModifier

invalidObjectMemberModifier

Error message

invalidObjectMemberModifier (dynamic errorMessage key)

What it means

`doVisitModifiers` validates each modifier against a bitmask of modifiers valid in the current context; when a modifier (e.g. `abstract` on a property, or `hidden` on a class) is not allowed, it throws `invalidObjectMemberModifier` with the modifier name interpolated into the message (AstBuilder.java:2998).

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/builder/AstBuilder.java:2998

      var previousValue = EconomicMaps.put(members, key, value);
      if (previousValue != null) {
        CompilerDirectives.transferToInterpreter();
        throw exceptionBuilder()
            .evalError("duplicateDefinition", new ProgramValue("", key))
            .withSourceSection(value.getHeaderSection())
            .build();
      }
    }
  }

  private int doVisitModifiers(
      List<? extends Modifier> modifiers, int validModifiers, String errorMessage) {

    var result = VmModifier.NONE;
    for (var ctx : modifiers) {
      int modifier = visitModifier(ctx);
      if ((modifier & validModifiers) == 0) {
        throw exceptionBuilder()
            .evalError(errorMessage, ctx.getValue().name().toLowerCase(Locale.ROOT))
            .withSourceSection(createSourceSection(ctx))
            .build();
      }
      result += modifier;
    }

    // flag modifier combinations that are never valid right away

    if (VmModifier.isExternal(result) && !ModuleKeys.isStdLibModule(moduleKey)) {
      throw exceptionBuilder()
          .evalError("cannotDefineExternalMember")
          .withSourceSection(createSourceSection(modifiers, ModifierValue.EXTERNAL))
          .build();
    }

    if (VmModifier.isLocal(result) && VmModifier.isHidden(result)) {
      throw exceptionBuilder()

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Read the interpolated modifier name in the message and remove it from that declaration.
  2. Check Pkl docs for modifiers valid for the member kind (properties: `local`, `hidden`, `fixed`, `external`; classes: `open`, `abstract`, `open` etc.).
  3. Move the modifier to the correct declaration site if it belongs elsewhere.

Example fix

// before
abstract foo = 1
// after
foo = 1
Defensive patterns

Strategy: validation

Validate before calling

// valid member modifiers per Pkl grammar: local, hidden, fixed, external, abstract
const VALID = new Set(["local", "hidden", "fixed", "external", "abstract", "open"]);
const mods = [...pklSource.matchAll(/^\s*([a-zA-Z]+)\s+[a-zA-Z_]\w*/gm)].map(m => m[1]);
mods.forEach(m => { if (!VALID.has(m)) throw new Error(`invalid modifier: ${m}`); });

Prevention

When it happens

Trigger: Using a modifier outside its allowed context, e.g. `open`/`abstract` on a non-class member, `fixed` on an object method, or any member modifier at module level where only a subset is valid.

Common situations: Copy-pasting modifiers between property/class declarations; misunderstanding which modifiers apply to object members vs classes; typos producing unexpected modifier placements.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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