apple/pkl · error · VmException
cannotRenderNonScalarMap
cannotRenderNonScalarMap
Error message
cannotRenderNonScalarMap
What it means
Renderer map keys must be scalar values. cannotRenderNonScalarKey throws cannotRenderNonScalarMap when the enclosing value is a VmMap and a key is a non-scalar (e.g. an object, listing, or collection). Target output formats cannot represent composite keys, so rendering aborts with the enclosing Map and offending Key attached.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/stdlib/AbstractRenderer.java:445
@Override
public void visitFunction(VmFunction value) {
cannotRenderTypeAddConverter(value);
}
protected void cannotRenderNonStringKey(Object key) {
assert enclosingValue != null;
var isMap = enclosingValue instanceof VmMap;
throw new VmExceptionBuilder()
.evalError(isMap ? "cannotRenderNonStringMap" : "cannotRenderObjectWithNonStringKey", name)
.withProgramValue(isMap ? "Map" : "Object", enclosingValue)
.withProgramValue("Key", key)
.build();
}
protected void cannotRenderNonScalarKey(Object key) {
assert enclosingValue != null;
var isMap = enclosingValue instanceof VmMap;
throw new VmExceptionBuilder()
.evalError(isMap ? "cannotRenderNonScalarMap" : "cannotRenderObjectWithNonScalarKey", name)
.withProgramValue(isMap ? "Map" : "Object", enclosingValue)
.withProgramValue("Key", key)
.build();
}
}
View on GitHub (pinned to f3efcbfc9b)
Solutions
- Replace the composite key with a scalar: a String derived from it (e.g. its `toString()` or a stable id field).
- Use an identifying property of the object (e.g. `obj.name`) as the key instead of the object itself.
- If association of composite data is needed, store it as the value or in a Listing of pairs.
- Log/inspect the reported `Key` program value to find where the composite key originates.
Example fix
// before
Mapping { [List(1, 2)] = "pair" }
// after
Mapping { ["1-2"] = "pair" } // stringified scalar key Defensive patterns
Strategy: validation
Validate before calling
// ensure keys are scalars before rendering function hasScalarKeys(m: Map) = m.keys.every((k) -> k is String || k is Number || k is Boolean)
Try / catch
try { render(mapValue) } catch (e) { if (e.message.contains('cannotRenderNonScalarMap')) render(keyToId(mapValue)) else throw e } Prevention
- Never use objects/collections as Map keys
- Derive scalar keys from an id/name property of composite values
- Inspect the Key program value in the error to locate the offending key source
When it happens
Trigger: Rendering a Map that contains a key which is itself a non-scalar value such as a Dynamic object, Listing, Map, or other composite value.
Common situations: Using objects or collections as Map keys by accident; building indexes keyed by parsed structures; nested data conversion that placed a collection where a scalar key was expected.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- cannotRenderNonStringMap
- cannotRenderObjectWithElementsAndOtherMembers
- Values of type `Duration` cannot be rendered as JSON. Value:
- Values of type `DataSize` cannot be rendered as JSON. Value:
- Values of type `Bytes` cannot be rendered as JSON. Value: %s
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/fb7804954a167ee3.
Report an issue: GitHub.