pentaho/pentaho-kettle · error · KettleException
AvroInput.Error.MalformedPathMap
AvroInput.Error.MalformedPathMap
Error message
AvroInput.Error.MalformedPathMap
What it means
The map-walking branch of convertToKettleValue found no remaining path parts when it needed one: the field's Avro path terminated at a MAP object but no key selector followed. The reader cannot look up a key in the map, so it throws this KettleException.
Solutions
- Append a key selector to the path: '$.mymap[mykey]'.
- If you want the whole map expanded, use the '[*]' expansion form: '$.mymap[*]'.
- Verify the schema: if the field genuinely is a scalar, correct the path to point at the scalar leaf.
Example fix
// before $.attributes // after (map is an object, key needed) $.attributes[color]
Defensive patterns
Strategy: validation
Validate before calling
// Ensure a path that reaches a MAP node has a '[key]' after it
if (schema.getField(path).schema().getType() == Schema.Type.MAP
&& !path.matches(".*\\[.+\\]$")) {
throw new IllegalArgumentException("Path to map needs [key]: " + path);
} Type guard
boolean mapPathHasKey(String path, Schema fieldSchema) {
return fieldSchema.getType() != Schema.Type.MAP
|| (path != null && path.matches(".*\\[.+\\].*$"));
} Try / catch
try {
Object v = reader.convertToKettleValue(...);
} catch (KettleException e) {
if (e.getMessage().contains("MalformedPathMap")) {
// fix the field path to include a [key] selector
} else throw e;
} Prevention
- Never end a field path at a map container
- Always append '[key]' or use '[*]' expansion after a map node
- Validate paths against the schema before running the transformation
When it happens
Trigger: A field path ends exactly at a map node (e.g. '$.mymap' where mymap is a map), so getTempParts() is empty when the map converter runs; or the path was consumed by earlier segments leaving nothing for the map lookup.
Common situations: Typing a path that stops at a map container while selecting a non-map Pentaho output type; forgetting the '[key]' bracket after a map name; schema changed so a formerly scalar field is now a map.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- AvroInput.Error.MalformedPathArray
- AvroInput.Error.MalformedPathArray2
- AvroInput.Error.MalformedPathMap2
- AvroInput.Error.MutipleDifferentExpansions
- AvroInput.Error.PathContainsMultipleExpansions
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/ff842e818ddcb184.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/input/AvroNestedReader.java:443
/**
* Processes a map at this point in the path.
*
* @param map the map to process
* @param s the current schema at this point in the path
* @param ignoreMissing true if null is to be returned for user fields that don't appear in the schema
* @return the field value or null for out-of-bounds array indexes, non-existent map keys or unsupported avro types.
* @throws KettleException if a problem occurs
*/
public Object convertToKettleValue( AvroInputField avroInputField,
Map<Utf8, Object> map, Schema s, Schema defaultSchema, boolean ignoreMissing )
throws KettleException {
if ( map == null ) {
return null;
}
if ( avroInputField.getTempParts().size() == 0 ) {
throw new KettleException( BaseMessages.getString( PKG, "AvroInput.Error.MalformedPathMap" ) );
}
String part = avroInputField.getTempParts().remove( 0 );
if ( !( part.charAt( 0 ) == '[' ) ) {
throw new KettleException( BaseMessages.getString( PKG, "AvroInput.Error.MalformedPathMap2", part ) );
}
String key = part.substring( 1, part.indexOf( ']' ) );
if ( part.indexOf( ']' ) < part.length() - 1 ) {
// more dimensions to the array/map
part = part.substring( part.indexOf( ']' ) + 1, part.length() );
avroInputField.getTempParts().add( 0, part );
}
Object value = map.get( new Utf8( key ) );
if ( value == null ) {
return null;View on GitHub (pinned to f3058517a1)