apple/pkl · error · NoSuchChildException
Leaf node `%s` of type `%s` does not have a child named `%s`
Error message
Leaf node `%s` of type `%s` does not have a child named `%s`.
What it means
LeafConfig wraps a scalar Pkl value (string, int, boolean, etc.). By definition a leaf has no children, so any attempt to read a child property from it unconditionally throws NoSuchChildException naming the leaf's value type and the requested child name. The error exists to convert a structural mistake — treating a scalar as an object — into a clear diagnostic.
Source
Thrown at pkl-config-java/src/main/java/org/pkl/config/java/LeafConfig.java:36
import org.pkl.config.java.mapper.ValueMapper;
import org.pkl.core.PClassInfo;
class LeafConfig extends AbstractConfig {
private final Object value;
LeafConfig(String qualifiedName, ValueMapper mapper, Object value) {
super(qualifiedName, mapper);
this.value = value;
}
@Override
public Object getRawValue() {
return value;
}
@Override
protected Object getRawChildValue(String propertyName) {
throw new NoSuchChildException(
String.format(
"Leaf node `%s` of type `%s` does not have a child named `%s`.",
qualifiedName, PClassInfo.forValue(value).getQualifiedName(), propertyName),
propertyName);
}
}
View on GitHub (pinned to f3efcbfc9b)
Solutions
- Call getRawValue() (or the typed value getter) on the node instead of requesting children.
- Verify the node's structure against the .pkl source; update access code to match whether it is an object or scalar.
- Regenerate typed config classes after schema changes.
- Use instanceof/Config subclass checks (CompositeConfig vs LeafConfig) before navigating children.
Example fix
// before
Object child = leafConfig.getChild("name"); // leaf has no children
// after
Object value = leafConfig.getRawValue();
if (value instanceof Map<?,?> map) {
Object child = map.get("name");
} Defensive patterns
Strategy: type-guard
Validate before calling
// check node kind before navigating children
if (node instanceof LeafConfig) {
Object value = ((LeafConfig) node).getRawValue();
// treat as scalar; do not call getChild
} Type guard
static boolean isLeaf(Config node) {
return node instanceof LeafConfig;
} Try / catch
try {
return node.getChild(name);
} catch (NoSuchChildException e) {
if (node instanceof LeafConfig leaf) {
return leaf.getRawValue(); // caller actually wanted the scalar
}
throw e;
} Prevention
- Regenerate typed accessors after any schema change that converts objects to scalars
- Check node type (Composite vs Leaf vs Map) before generic tree navigation
- Keep .pkl module and generated Java code in version lockstep
- Prefer generated accessors over reflective/string-based child lookups
When it happens
Trigger: Calling getChild/property accessors (routed to getRawChildValue) on a config node that wraps a leaf value, e.g. config.get("someScalar").get("field") or string-keyed access on a scalar node.
Common situations: The .pkl schema changed a nested object into a scalar (or vice versa) while the Java access code still expects an object; navigating config generically without checking node kind first; mis-typed generated accessor invoked on the wrong node.
Related errors
- Node `%s` of type `%s` does not have a property named `%s`.
- Node `%s` of type `%s` does not have a key named `%s`. Avail
- noPackageDefinedByProject
- JavaType token must be parameterized.
- Did not find expected Java class `%s` on the classpath for P
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/1745471e3fc6375b.
Report an issue: GitHub.