apple/pkl · error · VmReferenceAccessError

externalClass

Error message

externalClass

What it means

Raised when code references the `output` property of a Module through the Reference property-type machinery. Module.output is defined in an external (base) class, and Pkl forbids referencing properties originally defined in external classes — the only such subclassable case being Module.output.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/runtime/VmReference.java:243

    }
    // restriction: cannot reference Listing/Mapping.default
    if (clazz.getPClass().getInfo() == PClassInfo.Listing
        || clazz.getPClass().getInfo() == PClassInfo.Mapping) {
      var errorType =
          property.equals("default")
              ? VmReferenceAccessErrorType.DEFAULT_MEMBER
              : VmReferenceAccessErrorType.CANNOT_FIND_MEMBER;
      throw new VmReferenceAccessError(type, errorType);
    }
    var baseModule = BaseModule.getModuleClass().export();
    // restriction: cannot reference Module.output.
    //   generalized: properties originally defined in external classes; the only extant example.
    // This is implemented specifically because this is the only case where an external class
    //   containing a property can be subclassed.
    // And this can't check prop.getOwner().isExternal() because fully overriding the property with
    //   a new type annotation means the owner isn't Module.
    if (clazz.getPClass().isSubclassOf(baseModule) && property.equals("output")) {
      throw new VmReferenceAccessError(
          new PType.Class(baseModule), VmReferenceAccessErrorType.EXTERNAL_CLASS);
    }

    // dot access on `Reference<D, Null>` gives `Reference<D, Null>`
    if (clazz.getPClass().getInfo() == PClassInfo.Null) {
      result.add(clazz);
      return;
    }

    var prop = clazz.getPClass().getAllProperties().get(property);
    if (prop == null) {
      throw new VmReferenceAccessError(type, VmReferenceAccessErrorType.CANNOT_FIND_MEMBER);
    }

    // restriction: cannot reference external properties
    if (prop.isExternal()) {
      throw new VmReferenceAccessError(type, VmReferenceAccessErrorType.EXTERNAL_MEMBER);
    }

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Avoid referencing `module.output` inside Pkl; output is meant for the host/consumer.
  2. Expose the needed data as a regular (non-output) property on the module.
  3. If you need the rendered text, evaluate and export from the host side instead.
  4. Move the data out of `output` into a named property that reference-checking allows.

Example fix

// before
x = MyModule.output
// after (in MyModule)
rendered = "..." // regular property
// then
x = MyModule.rendered
Defensive patterns

Strategy: validation

Validate before calling

// Pkl: ensure you never reference Module.output in reference positions
// expose data as a normal property instead
rendered = "..."

Try / catch

try {
  eval(src);
} catch (EvalException e) {
  if (e.getMessage().contains("externalClass")) {
    // you referenced a property from an external class (e.g. Module.output)
  }
}

Prevention

When it happens

Trigger: Referencing `someModule.output` in a context validated by getCandidatePropertyType (e.g. property type references in amends/extends scenarios).

Common situations: Trying to read another module's rendered output inside Pkl; using `output` in type positions or reference-checking paths rather than through normal evaluation.

Related errors


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