apple/pkl · error

invalid for-generator modifier (dynamic errorMessageKey)

Error message

invalid for-generator modifier (dynamic errorMessageKey)

What it means

Pkl's AST builder rejects modifiers such as `...` (spread), `*` (defaults), or `when`/`is` predicates in a `for` generator position where they are not allowed. The builder walks up the parse tree to the enclosing ForGenerator node and attaches the error to the generator's source span. It means the object-spread/amend syntax you wrote cannot be combined with a for-generator in that position.

Source

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

  private @Nullable Pair<@Nullable FrameDescriptorBuilder, FrameSlotVariable[]>
      createFrameDescriptorBuilderAndSlotVariables(ObjectBody body) {
    if (body.getParameters().isEmpty()) return null;

    var builder = new FrameDescriptorBuilder(body.getParameters().size());
    return Pair.of(builder, getSlotVariables(body.getParameters(), builder));
  }

  private void checkNotInsideForGenerator(Node ctx, String errorMessageKey) {
    if (!symbolTable.getCurrentScope().isForGeneratorScope()) {
      return;
    }
    var forExprCtx = ctx.parent();
    while (forExprCtx != null
        && forExprCtx.getClass() != org.pkl.parser.syntax.ObjectMember.ForGenerator.class) {
      forExprCtx = forExprCtx.parent();
    }
    assert forExprCtx != null;
    throw exceptionBuilder()
        .evalError(errorMessageKey)
        .withSourceSection(
            createSourceSection(
                ((org.pkl.parser.syntax.ObjectMember.ForGenerator) forExprCtx).forSpan()))
        .build();
  }

  private void checkDuplicateMember(
      org.pkl.core.runtime.Identifier memberName,
      SourceSection headerSection,
      // use Set<String> rather than Set<Identifier>
      // to detect conflicts between local and non-local identifiers
      Set<String> visited) {

    if (!visited.add(memberName.toString())) {
      throw exceptionBuilder()
          .evalError("duplicateDefinition", memberName)
          .withSourceSection(headerSection)

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Move the spread/default/conditional modifier out of the for-generator body onto a plain object member or the enclosing object
  2. Iterate and emit plain properties inside the for body instead of using the invalid modifier
  3. Check the Pkl language spec for which modifiers are legal on for-generator members

Example fix

// before
foo {
  for (item in items) {
    ...item.props // invalid modifier in for generator
  }
}
// after
foo {
  ...items.first.props
  for (item in items.drop(1)) {
    ["item-\(item.name)"] { ...item.props }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// before relying on modifiers inside a for generator, keep the body to plain members:
function usesOnlyPlainMembers(body: Listing<*>) = body.isEmpty() // review manually: for(...) { ... } must not contain `...`/amend modifiers

Prevention

When it happens

Trigger: Writing an object member whose modifier is invalid inside a `for (...) { ... }` generator in a Pkl module, e.g. spreading `...expr` or using an amend modifier on a for-generated member where the grammar disallows it.

Common situations: Copy-pasting object-spread patterns into for-generator bodies; assuming `for` generators support the same spread/defaults modifiers as plain object bodies; refactoring amends into generated members.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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