apple/pkl · error · RendererException

The top-level value of a YAML stream must have type `Collect

Error message

The top-level value of a YAML stream must have type `Collection`, but got type `%s`.

What it means

YamlRenderer.renderDocument, when rendering a YAML stream (isStream == true), requires the top-level value to be an Iterable so it can emit each element as a separate YAML document. Any other type throws RendererException stating the actual type name.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/YamlRenderer.java:92

              @Override
              public void write(String str, int off, int len) {
                try {
                  writer.write(str, off, len);
                } catch (IOException e) {
                  throw new UncheckedIOException(e);
                }
              }
            });

    this.omitNullProperties = omitNullProperties;
    this.isStream = isStream;
  }

  @Override
  public void renderDocument(Object value) {
    if (isStream) {
      if (!(value instanceof Iterable<?> iterable)) {
        throw new RendererException(
            String.format(
                "The top-level value of a YAML stream must have type `Collection`, but got type `%s`.",
                value.getClass().getTypeName()));
      }
      emitter.emit(new StreamStartEvent());
      for (var elem : iterable) {
        emitter.emit(new DocumentStartEvent(false, Optional.empty(), Map.of()));
        visitor.visit(elem);
        emitter.emit(new DocumentEndEvent(false));
      }
      emitter.emit(new StreamEndEvent());
    } else {
      // a top-level YAML value can have any type
      renderValue(value);
    }
  }

  @Override

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Disable stream mode (renderer.setStream(false)) if you want a single YAML document.
  2. Wrap the value in a List before rendering when stream output is required.
  3. Change the Pkl module's output value to a List/Iterable so each element becomes its own document.

Example fix

// before
renderer.setStream(true);
renderer.renderDocument(mapping); // throws
// after
renderer.setStream(false);
renderer.renderDocument(mapping);
Defensive patterns

Strategy: type-guard

Validate before calling

if (isStream && !(value instanceof Iterable)) {
  throw new IllegalArgumentException("stream output requires a top-level list");
}

Type guard

boolean isRenderableStreamRoot(Object v) { return v instanceof Iterable<?>; }

Try / catch

try {
  renderer.renderDocument(value);
} catch (RendererException e) {
  if (e.getMessage().contains("YAML stream must have type `Collection`")) {
    renderer.renderDocument(List.of(value)); // or disable stream mode
  } else throw e;
}

Prevention

When it happens

Trigger: Creating a YamlRenderer with setStream(true) (or stream output mode) and calling renderDocument with a non-collection value such as a Mapping, List without Iterable at that level, String, or Number.

Common situations: Rendering a single Pkl object to YAML with stream mode accidentally enabled; CLI `pkl eval -f yaml` with a stream-flavored output when the module's output value is not a list.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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