apple/pkl · error · ConversionException
Error invoking constructor `%s`.
Error message
Error invoking constructor `%s`.
What it means
After all constructor arguments are converted, pkl-config-java invokes the target constructor via a MethodHandle (invokeWithArguments). If the invocation throws any Throwable — e.g. the constructor's own validation code threw, arguments are wrong after conversion, or the handle's type doesn't match the arguments — it is wrapped in this ConversionException with the constructor handle in the message.
Source
Thrown at pkl-config-java/src/main/java/org/pkl/config/java/mapper/PObjectToDataObject.java:228
} catch (ConversionException e) {
throw new ConversionException(
String.format(
"Error converting property `%s` in Pkl object of type `%s` "
+ "to equally named constructor parameter in Java class `%s`: "
+ e.getMessage(),
param.first,
value.getClassInfo(),
Reflection.toRawType(targetType).getTypeName()),
e.getCause());
}
}
try {
@SuppressWarnings("unchecked")
var result = (T) constructorHandle.invokeWithArguments(args);
return result;
} catch (Throwable t) {
throw new ConversionException(
String.format("Error invoking constructor `%s`.", constructorHandle), t);
}
}
}
}
View on GitHub (pinned to f3efcbfc9b)
Solutions
- Inspect the cause chain (getCause()) — the real exception is thrown by your constructor body; fix the constructor or the offending config value.
- Fix the Pkl value so it passes the constructor's validation (e.g. valid ranges, non-null fields).
- If a null is being passed to a primitive parameter, change the Java parameter to a wrapper type or give the Pkl property a non-null default.
- Ensure the converted class and its dependencies load cleanly (no static initializer failures, consistent class versions).
Example fix
// before: constructor rejects config value
public Server(int port) {
if (port <= 0) throw new IllegalArgumentException("port must be > 0");
...
}
// config: port = -1
// after
// config: port = 8080 Defensive patterns
Strategy: try-catch
Try / catch
try {
return converter.convert(pklObject, valueMapper);
} catch (ConversionException e) {
if (e.getMessage().startsWith("Error invoking constructor")) {
Throwable root = e;
while (root.getCause() != null) root = root.getCause();
throw new ConfigLoadException("Constructor rejected config values: " + root, root);
}
throw e;
} Prevention
- Unwrap and log getCause() to see the real constructor failure
- Avoid constructors with side-effecting validation for config-mapped classes, or keep validation messages descriptive
- Ensure null Pkl values never map to primitive parameters (use wrapper types or non-null defaults)
- Cover constructor validation rules with tests against representative config values
When it happens
Trigger: Converter.convert reaching constructorHandle.invokeWithArguments(args) where the constructor body throws (IllegalArgumentException on validation, NPE, custom checks), or argument arity/types mismatch the MethodHandle signature (e.g. null passed to a primitive parameter).
Common situations: Java constructor performs validation (e.g. requires port > 0) and the Pkl config violates it; null Pkl value mapped into a primitive parameter; class initialization failure (ExceptionInInitializerError); incompatible cached converter after hot code replacement.
Related errors
- JavaType token must be parameterized.
- Error invoking constructor of class `%s`.
- Error accessing constructor of class `%s`.
- Error invoking constructor of class `%s`.
- 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/5d4304ead0889ec6.
Report an issue: GitHub.