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();
      }
    }

    @Override

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Convert the Dynamic value into a typed Pkl class so the renderer can map it to a protobuf message
  2. Register/add a custom converter for the type in the ProtobufRenderer configuration
  3. 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

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


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