apple/pkl · error · RendererException

Values of type `Duration` cannot be rendered as JSON. Value:

Error message

Values of type `Duration` cannot be rendered as JSON. Value: %s

What it means

JsonRenderer throws this RendererException whenever it is asked to render a Pkl Duration value as JSON, because the JSON output format has no representation for durations. It is a deliberate hard stop rather than a silent coercion.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/JsonRenderer.java:95

      try {
        writer.value(value);
      } catch (IOException e) {
        throw new UncheckedIOException(e);
      }
    }

    @Override
    public void visitBoolean(Boolean value) {
      try {
        writer.value(value);
      } catch (IOException e) {
        throw new UncheckedIOException(e);
      }
    }

    @Override
    public void visitDuration(Duration value) {
      throw new RendererException(
          String.format("Values of type `Duration` cannot be rendered as JSON. Value: %s", value));
    }

    @Override
    public void visitDataSize(DataSize value) {
      throw new RendererException(
          String.format("Values of type `DataSize` cannot be rendered as JSON. Value: %s", value));
    }

    @Override
    public void visitBytes(byte[] value) {
      throw new RendererException(
          String.format(
              "Values of type `Bytes` cannot be rendered as JSON. Value: %s", (Object) value));
    }

    // Pair coming from the runtime can never admit null (in-language null is represented as PNull)
    @SuppressWarnings("DataFlowIssue")

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Convert the Duration to a number or string before rendering (e.g. value.value in seconds or value.isoString())
  2. Restructure the module so duration fields are excluded or represented as Int/Float/String
  3. Use a renderer/format that supports durations if JSON is not required

Example fix

// before
prop timeout: Duration = 5.min
// after
prop timeoutSeconds: Number = 5.min.value // 300
Defensive patterns

Strategy: type-guard

Validate before calling

// before rendering, walk values and reject unsupported types
if (value instanceof Duration) {
  throw new IllegalArgumentException("convert Duration before JSON rendering");
}

Type guard

boolean isJsonRenderable(Object v) {
  return !(v instanceof Duration || v instanceof DataSize || v instanceof byte[]);
}

Try / catch

try {
  renderer.render(value);
} catch (RendererException e) {
  // value type unsupported by JSON renderer; convert or exclude it
  LOG.error("JSON rendering unsupported: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Rendering a Pkl module/property tree to JSON while a property evaluates to a Duration (e.g. `x = 5.min`), via any code path that dispatches visitDuration on the renderer.

Common situations: JSON-rendering an API or config module that contains duration-typed fields such as timeouts, intervals, or TTLs.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


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