apple/pkl · error · VmException

cannotInferParent

cannotInferParent

Error message

cannotInferParent

What it means

When an object literal (`new ...`) appears in certain positions, Pkl must infer its parent (the class being instantiated) from surrounding context. If the direct parent expression is a `let` binding whose binding expression is the object, the builder cannot determine the parent type and throws cannotInferParent (a known unimplemented case, per the TODO).

Solutions

  1. Give the type explicitly: write `new Person {}` instead of `new {}`.
  2. Assign to a typed property instead of using let, letting the property's type annotate the object.
  3. Introduce an intermediate local via a typed lambda parameter or refactor to a function.

Example fix

// before
let (x: Person = new {}) { x.name }
// after
let (x = new Person {}) { x.name }
Defensive patterns

Strategy: type-guard

Validate before calling

// Prefer explicit types on every `new` inside a let:
let (x = new Person {}) { ... }

Prevention

When it happens

Trigger: Writing `let (x: Person = new {}) { ... }` — an `new {}` object as the binding expression of a let, so `InferParent` has no context node.

Common situations: Attempting local scoped object construction inside a let block, a style that works in some dynamic languages but is unsupported here.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

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

              ReadPropertyNodeGen.create(
                  createSourceSection(expr.newSpan()),
                  org.pkl.core.runtime.Identifier.DEFAULT,
                  new GetReceiverNode()),
              new GetMemberKeyNode());
    } else if (parent instanceof ClassMethod || parent instanceof ObjectMethod) {
      var isObjectMethod =
          parent instanceof ObjectMethod
              || parent.parent() instanceof Module && moduleInfo.isAmend();
      org.pkl.core.runtime.Identifier scopeName = scope.getName();
      inferredParentNode =
          isObjectMethod
              ? InferParentWithinObjectMethodNodeGen.create(
                  createSourceSection(expr.newSpan()), language, scopeName, new GetOwnerNode())
              : InferParentWithinMethodNodeGen.create(
                  createSourceSection(expr.newSpan()), language, scopeName, new GetOwnerNode());
    } else if (parent instanceof LetExpr letExpr && letExpr.getBindingExpr() == child) {
      // TODO correctly infer parent, e.g. `let (x: Person = new {}) ...`
      throw exceptionBuilder()
          .evalError("cannotInferParent")
          .withSourceSection(createSourceSection(expr.newSpan()))
          .build();
    } else if (parent instanceof ArgumentList argumentList) {
      // cases we can't cover currently
      // - FunctionN.apply: the parameter type nodes are not stored
      // - pkl.base intrinsic constructors: List(), Set(), Map(), Bytes()
      // - generic methods: pkl.base#Pair(), etc.
      // these will throw cannotInferParent at runtime
      var sourceSection = createSourceSection(expr.newSpan());
      var argIndex = argumentList.getArguments().indexOf(child);
      inferredParentNode =
          InferParentWithinMethodArgumentNodeGen.create(sourceSection, language, argIndex);
    } else {
      throw exceptionBuilder()
          .evalError("cannotInferParent")
          .withSourceSection(createSourceSection(expr.newSpan()))
          .build();

View on GitHub (pinned to f3efcbfc9b)