pentaho/pentaho-kettle · error · KettleException
AvroInput.Error.UnionError2
Error message
AvroInput.Error.UnionError2
What it means
Kettle exception thrown by checkUnion when a two-type union does not include NULL. The reader expects nullable unions ['null', X]; a union of two non-null types (e.g. ['int','string']) has no null branch and cannot be processed.
Solutions
- Change the union to include a null branch: ["null", <type>], typically with null as the default branch.
- Pick one concrete type and remove the union if both branches are non-null.
- Normalize the schema upstream (schema resolution/evolution step) before Pentaho reads it.
- Verify the configured path targets the right field; a neighboring field may actually be the nullable one.
Example fix
// before
{"name":"v","type":["int","long"]}
// after
{"name":"v","type":["null","long"],"default":null} Defensive patterns
Strategy: validation
Validate before calling
// Require a NULL branch in any union before reading
List<Schema> types = fieldSchema.getTypes();
if (types.size() == 2 && types.stream().noneMatch(t -> t.getType() == Schema.Type.NULL)) {
throw new IllegalArgumentException("Union ['" + types.get(0) + "','" + types.get(1) + "'] lacks a null branch");
} Try / catch
try {
value = reader.convertToKettleValue(record, schema, field);
} catch (KettleException e) {
if (e.getMessage().contains("UnionError2")) {
logError("Union has no null branch — add 'null' to the union in the schema", e);
}
} Prevention
- Adopt the Avro null-default convention: ["null", T] with "default": null
- Reject non-nullable two-way unions at schema registration time
- Diff writer schemas against your read schema before onboarding new producers
When it happens
Trigger: checkUnion iterates union branches looking for Schema.Type.NULL; no branch is NULL so the 'ok' flag remains false and the exception is thrown (the non-null branch is returned otherwise).
Common situations: Files written with non-nullable two-way unions; schema regenerated without the null default; data producers that avoid Avro null-default convention; Kafka Avro records with ["int","long"] style unions.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- AvroInput.Error.UnionError1
- AvroInput.Error.UnexpectedArrayElementTypeAtNonExpansionPoin…
- AvroInput.Error.CantLoadIncommingSchemaAndNoDefault
- AvroInput.Error.EncounteredAPrimitivePriorToMapExpansion
- AvroInput.Error.IncommingSchemaIsMissingAndNoDefault
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/4d527f8285b0723b.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/input/AvroNestedReader.java:870
List<Schema> types = s.getTypes();
// the type other than null
Schema otherSchema = null;
if ( types.size() != 2 ) {
throw new KettleException( BaseMessages.getString( PKG, "AvroInput.Error.UnionError1" ) );
}
for ( Schema p : types ) {
if ( p.getType() == Schema.Type.NULL ) {
ok = true;
} else {
otherSchema = p;
}
}
if ( !ok ) {
throw new KettleException( BaseMessages.getString( PKG, "AvroInput.Error.UnionError2" ) );
}
return otherSchema;
}
/**
* Cleanses a string path by ensuring that any variables names present in the path do not contain "."s (replaces any
* dots with underscores).
*
* @param path the path to cleanse
* @return the cleansed path
*/
public static String cleansePath( String path ) {
// look for variables and convert any "." to "_"
int index = path.indexOf( "${" );
int endIndex = 0;View on GitHub (pinned to f3058517a1)