apple/pkl · error · VmException
cannotRenderTypeAddConverter
cannotRenderTypeAddConverter
Error message
cannotRenderTypeAddConverter
What it means
Protobuf rendering does not support `Dynamic` objects because protobuf requires a known schema/type; the renderer tells you to add a converter instead of guessing. Thrown when traversal reaches a VmDynamic node.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/stdlib/protobuf/RendererNodes.java:186
}
assert propertyPath.isEmpty() && wrapperRequirement.isEmpty() : "Corrupted traversal stack.";
wrapperRequirement.push(false);
visit(value);
var wrap = wrapperRequirement.pop();
assert !wrap && propertyPath.isEmpty() && wrapperRequirement.isEmpty()
: "Corrupted traversal stack.";
}
@Override
protected void visitRenderDirective(VmTyped value) {
writePropertyName();
// append verbatim
builder.append(VmUtils.readTextProperty(value));
}
@Override
protected void startDynamic(VmDynamic value) {
throw new VmExceptionBuilder()
.evalError("cannotRenderTypeAddConverter", "Dynamic", "Protobuf")
.withProgramValue("Value", value)
.build();
}
@Override
protected void endDynamic(VmDynamic value, boolean isEmpty) {}
@Override
protected void startTyped(VmTyped value) {
wrapperRequirement.push(false);
if (!propertyPath.isEmpty()) {
writePropertyName();
startMessage();
}
}
@OverrideView on GitHub (pinned to f3efcbfc9b)
Solutions
- Convert the Dynamic value into a typed Pkl class so the renderer can map it to a protobuf message
- Register/add a custom converter for the type in the ProtobufRenderer configuration
- Replace Dynamic usage with defined classes in the module being rendered
Example fix
// before
output.value = new Dynamic { name = "x" }
output.renderer = new ProtobufRenderer
// after
class Person { name: String }
output.value = (Person) { name = "x" }
output.renderer = new ProtobufRenderer Defensive patterns
Strategy: fallback
Validate before calling
function hasNoDynamic(v) { return !containsKind(v, 'Dynamic'); } Type guard
const isTypedNotDynamic = (v) => isPklTyped(v) && !isPklDynamic(v);
Try / catch
try { renderAsProtobuf(value) } catch (e) { if (e.code === 'cannotRenderTypeAddConverter') { /* fall back to JSON or add converter */ } else throw e } Prevention
- Replace Dynamic values with typed classes in protobuf-rendered modules
- Configure converters for any third-party Dynamic values
- Keep Dynamic usage confined to prototyping, not protobuf output paths
When it happens
Trigger: Rendering a value to protobuf where a `Dynamic` object appears (as the top-level value or nested property) and no custom converter handles that type.
Common situations: Using `new Dynamic { ... }` or `dynamic { ... }` values inside a module rendered to protobuf; prototyping with Dynamic values then switching output format to protobuf without converting to typed classes.
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
- cannotResolveTypeForProtobuf
- invalidProtobufTopLevelValue
- cannotRenderProtobufMapKey
- Values of type `Duration` cannot be rendered as JSON. Value:
- Values of type `DataSize` cannot be rendered as JSON. Value:
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/7658e28837ae8572.
Report an issue: GitHub.