{"record":{"id":"cd05e8e8abe2aed3","repo":"apple/pkl","slug":"cannotinvokeabstractmethod","errorCode":"cannotInvokeAbstractMethod","errorMessage":"cannotInvokeAbstractMethod ${functionName}","messagePattern":"cannotInvokeAbstractMethod (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/ast/builder/CannotInvokeAbstractFunctionNode.java","lineNumber":34,"sourceCode":"package org.pkl.core.ast.builder;\n\nimport com.oracle.truffle.api.CompilerDirectives;\nimport com.oracle.truffle.api.frame.VirtualFrame;\nimport com.oracle.truffle.api.source.SourceSection;\nimport org.pkl.core.ast.ExpressionNode;\n\npublic final class CannotInvokeAbstractFunctionNode extends ExpressionNode {\n  private final String functionName;\n\n  public CannotInvokeAbstractFunctionNode(SourceSection section, String functionName) {\n    super(section);\n    this.functionName = functionName;\n  }\n\n  @Override\n  public Object executeGeneric(VirtualFrame frame) {\n    CompilerDirectives.transferToInterpreter();\n    throw exceptionBuilder().evalError(\"cannotInvokeAbstractMethod\", functionName).build();\n  }\n}\n","sourceCodeStart":16,"sourceCodeEnd":37,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/ast/builder/CannotInvokeAbstractFunctionNode.java#L16-L37","documentation":"This Truffle node is compiled in place of a call to an abstract (declaration-only) Pkl function. Executing it always throws: abstract functions have no body, so invoking one directly is undefined and Pkl reports cannotInvokeAbstractMethod with the function name.","triggerScenarios":"Calling an abstract function on an object that does not provide a concrete override — e.g. invoking `render()` on a value typed as an abstract module/class whose subtype was expected to implement it.","commonSituations":"Forgetting to override an abstract function in a subclass/typed object; calling methods on `new` instances of abstract types; refactoring renamed an override so it no longer matches.","solutions":["Provide a concrete override of the named function in the object/subclass being instantiated","Do not instantiate the abstract type directly; instantiate a concrete subtype","Fix override name/signature mismatch so the definition actually overrides the abstract member"],"exampleFix":"// before\nabstract class Renderer { function render(): String }\nrenderer = new Renderer {} // no override\n// after\nabstract class Renderer { function render(): String }\nrenderer = new Renderer { function render() = \"hello\" }","handlingStrategy":"type-guard","validationCode":"// pkl-side guard: only call when the receiver provides the function\n// renderer is ConcreteRenderer && renderer.hasProperty(\"render\")","typeGuard":"function canInvoke(obj, fn) { return obj.getClass().isConcrete && obj.hasProperty(fn) } // conceptually: ensure concrete subtype before calling","tryCatchPattern":"// Wrap invocation in try/catch for PklError matching cannotInvokeAbstractMethod, then fall back to a default implementation","preventionTips":["Never instantiate abstract classes/modules directly","Ensure every subtype overrides all abstract functions","Type values as the concrete subclass rather than the abstract supertype"],"tags":["pkl","abstract-method","call","truffle"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}