apple/pkl · error · VmException

cannotFindPropertyInObject

cannotFindPropertyInObject

Error message

Cannot find property `{0}` in object of type `{1}`.

What it means

In a typed object amendment (`amends SomeClass`), every member must correspond to a property that exists on the parent class. `checkIsValidTypedAmendment` walks the literal's members and throws `cannotFindProperty` when a member name is not a declared property of the class being amended (and is not local).

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/literal/SpecializedObjectLiteralNode.java:81

  protected final UnmodifiableEconomicMap<Object, ObjectMember> members;

  @CompilationFinal protected long maxListingMemberIndex = Long.MIN_VALUE;
  @CompilationFinal private boolean checkedIsValidMappingAmendment;

  // only runs once per VmClass (which often means once per PropertiesLiteralNode)
  // unless an XYZUncached specialization is active
  @TruffleBoundary
  @Idempotent
  protected boolean checkIsValidTypedAmendment(Object parent) {
    var parentClass = parent instanceof VmClass vmClass ? vmClass : VmUtils.getClass(parent);
    VmUtils.checkIsInstantiable(parentClass, getParentNode());

    for (var member : EconomicMaps.getValues(members)) {
      if (member.isLocal()) continue;

      var memberName = member.getName();
      if (!parentClass.hasProperty(memberName)) {
        throw exceptionBuilder()
            .cannotFindProperty(parentClass.getPrototype(), memberName, false, false)
            .withSourceSection(member.getHeaderSection())
            .build();
      }
      var classProperty = parentClass.getProperty(memberName);
      if (classProperty != null && classProperty.isConstOrFixed()) {
        // tailor error message based on whether an amends declaration is used or not
        // (i.e. `friends {}` vs. `friends = new {}`)
        // an amends declaration's body section includes the header section, whereas normal property
        // assignment's body section is the section after the equal sign.
        var isAmendsDeclaration =
            member.getHeaderSection().getCharIndex() == member.getBodySection().getCharIndex();
        var errMsg = isAmendsDeclaration ? "cannotAmendFixedProperty" : "cannotAssignFixedProperty";
        if (classProperty.isConst()) {
          errMsg = isAmendsDeclaration ? "cannotAmendConstProperty" : "cannotAssignConstProperty";
        }
        throw exceptionBuilder()
            .evalError(errMsg, memberName)

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Correct the member name to match an existing property of the amended class
  2. Remove the member if it does not belong to the parent type (use a plain `new` object or extension instead if you need to add properties)
  3. Regenerate/check the parent module's property list (`pkl eval` with docs, or read the class definition) to confirm the exact name

Example fix

// before
server { amends ServerConfig }
server { prot = 8080 } // typo
// after
server { port = 8080 } // matches ServerConfig.port
Defensive patterns

Strategy: validation

Validate before calling

// Before amending MyClass, confirm the property exists:
// pkl eval -y 'import "pkg.pkl"; (pkg.MyClass).toMap().keys'

Prevention

When it happens

Trigger: Writing `obj { ... amends MyClass }` with a member `foo = 1` where `MyClass` has no property `foo`; misspelling a property name; amending a class whose property was removed/renamed in a newer version of the module.

Common situations: Typo in property name when overriding defaults; upstream package updated and renamed a property; assuming `amends` behaves like object spread and can add new properties (it cannot for typed objects).

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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