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
- Give the type explicitly: write `new Person {}` instead of `new {}`.
- Assign to a typed property instead of using let, letting the property's type annotate the object.
- 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
- Always annotate `new` expressions in let bindings with their type (`new Person {}`).
- Avoid bare `new {}` as a let binding value; it has no inferable parent.
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
- cannotInferParent
- abstractMemberCannotHaveBody
- abstractMethodInNonAbstractType
- array
- Cannot convert pkl.base#Int
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)