{"record":{"id":"7323247e9ed9ae01","repo":"pentaho/pentaho-kettle","slug":"field-f-getformatfieldname-has-undefined-type","errorCode":null,"errorMessage":"Field: \" + f.getFormatFieldName() + \" has undefined type. ","messagePattern":"Field: \" \\+ f\\.getFormatFieldName\\(\\) \\+ \" has undefined type\\. ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/output/PentahoAvroOutputFormat.java","lineNumber":179,"sourceCode":"  }\n\n  protected ObjectNode getSchemaObjectNode() {\n    if ( schemaObjectNode == null ) {\n      if ( fields != null ) {\n        ObjectMapper mapper = new ObjectMapper();\n        schemaObjectNode = mapper.createObjectNode();\n\n        schemaObjectNode.put( AvroSpec.NAMESPACE_NODE, nameSpace );\n        schemaObjectNode.put( AvroSpec.TYPE_NODE, AvroSpec.TYPE_RECORD );\n        schemaObjectNode.put( AvroSpec.NAME_NODE, recordName );\n        schemaObjectNode.put( AvroSpec.DOC, docValue );\n\n        ArrayNode fieldNodes = mapper.createArrayNode();\n        Iterator<? extends IAvroOutputField> fields = this.fields.iterator();\n        while ( fields.hasNext() ) {\n          IAvroOutputField f = fields.next();\n          if ( f.getAvroType() == null ) {\n            throw new RuntimeException( \"Field: \" + f.getFormatFieldName() + \" has undefined type. \" );\n          }\n\n          AvroSpec.DataType type = f.getAvroType();\n          ObjectNode fieldNode = mapper.createObjectNode();\n\n          fieldNode.put( AvroSpec.NAME_NODE, f.getFormatFieldName() );\n          if ( type.isPrimitiveType() ) {\n            if ( f.getAllowNull() ) {\n              ArrayNode arrayNode = mapper.createArrayNode().add( AvroSpec.DataType.NULL.getType() );\n              arrayNode.add( type.getType() );\n              fieldNode.putPOJO( AvroSpec.TYPE_NODE, arrayNode );\n            } else {\n              fieldNode.put( AvroSpec.TYPE_NODE, type.getType() );\n            }\n          } else {\n            ObjectNode typeNode = mapper.createObjectNode();\n            typeNode.put( AvroSpec.LOGICAL_TYPE, type.getLogicalType() );\n            typeNode.put( AvroSpec.TYPE_NODE, type.getBaseType() );","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/avro-format/core/src/main/java/org/pentaho/di/trans/steps/avro/output/PentahoAvroOutputFormat.java#L161-L197","documentation":"RuntimeException thrown by PentahoAvroOutputFormat.getSchemaObjectNode when building the Avro schema JSON because one of the configured output fields has a null Avro type. Every field must have a concrete AvroSpec.DataType for the schema to be generated.","triggerScenarios":"Calling getSchemaObjectNode (via schemaObjectNode) while iterating this.fields and encountering an IAvroOutputField whose getAvroType() returns null — typically a field added in the step dialog without choosing an Avro type, or a field whose type failed to map.","commonSituations":"User configures the Avro Output step, adds a field row but leaves the Type column unset; a field type from the incoming stream has no Avro equivalent so the mapping produced null; metadata imported from an older/differently-versioned transformation where the type attribute was lost.","solutions":["Open the Avro Output step dialog and set an Avro type for every listed field","Remove fields that have no meaningful Avro type if they are not needed","Verify the incoming stream field types are supported; rename/retype unsupported fields (e.g. binary/binary-incompatible types) upstream","Recreate the step metadata if the transformation was authored in an incompatible Pentaho version","Wrap schema generation in a validation loop checking getAvroType() != null before calling schemaObjectNode"],"exampleFix":"// before\nIAvroOutputField f = fields.next();\nif ( f.getAvroType() == null ) { throw new RuntimeException( \"Field: \" + f.getFormatFieldName() + \" has undefined type. \" ); }\n// after: guard at call site\nfor ( IAvroOutputField f : outputMeta.getFields() ) {\n  if ( f.getAvroType() == null ) { throw new IllegalStateException( \"Set an Avro type for field \" + f.getFormatFieldName() ); }\n}","handlingStrategy":"validation","validationCode":"// validate fields before running the transformation\nfor ( IAvroOutputField f : meta.getAvroFields() ) {\n  if ( f.getAvroType() == null ) { throw new IllegalArgumentException( \"Set an Avro type for field: \" + f.getFormatFieldName() ); }\n}","typeGuard":"boolean hasValidTypes( List<IAvroOutputField> fields ) { return fields.stream().allMatch( f -> f.getAvroType() != null ); }","tryCatchPattern":"try { avroOutputFormat.schemaObjectNode(); }\ncatch ( RuntimeException e ) { if ( e.getMessage().contains( \"has undefined type\" ) ) { openStepDialogToFixFieldTypes(); } else { throw e; } }","preventionTips":["Always set the Type column for every field row in the Avro Output dialog","Validate step metadata programmatically before running transformations","Check field-type mapping compatibility after upgrading Pentaho or the avro-format plugin","Delete unused field rows instead of leaving them half-configured"],"tags":["avro","schema","configuration","type-mapping"],"backgroundTag":"missing-required-config-field","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}