apache/iceberg · error · ConfigException

Could not parse for

Error message

Could not parse ${field} for ${EXTERNAL_KAFKA_METADATA}

What it means

KafkaMetadataTransform.getExternalFieldAppender parses an external Kafka metadata config value expected as a comma-separated 'name,value' pair. If the string doesn't split into exactly two parts, ConfigException is thrown at connector configuration time.

Solutions

  1. Set the config value to exactly two comma-separated parts: '<fieldName>,<metadataValue>'.
  2. Check the connector properties file for stray commas or broken quoting.
  3. Consult the transform's docs for the exact expected format of EXTERNAL_KAFKA_METADATA.

Example fix

// before
"transform.external.kafka.metadata": "headers"
// after
"transform.external.kafka.metadata": "headerKey,headerValue"
Defensive patterns

Strategy: validation

Validate before calling

// Validate the config value shape before submitting the connector config
String v = props.getProperty("transform.external.kafka.metadata");
if (v != null && v.split(",", -1).length != 2) throw new IllegalArgumentException("expected '<name>,<value>': " + v);

Try / catch

try { ... } catch (org.apache.kafka.common.config.ConfigException e) { log.error("Bad transform config: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Configuring the transform with an external kafka metadata option whose value has more or fewer than one comma, e.g. 'topic' or 'a,b,c' instead of 'topic,partition'.

Common situations: Typos in the SMT config (missing the second element), accidental extra commas, or quoting issues in the connector properties file.

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.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/85cedd2ba6e49816. Report an issue: GitHub.

Appendix: source

Thrown at kafka-connect/kafka-connect-transforms/src/main/java/org/apache/iceberg/connect/transforms/KafkaMetadataTransform.java:68

    @Override
    public void addToSchema(SchemaBuilder builder) {}

    @Override
    public void addToStruct(SinkRecord record, Struct struct) {}

    @Override
    public void addToMap(SinkRecord record, Map<String, Object> map) {}
  }

  private static RecordAppender getExternalFieldAppender(
      String field, Function<String, String> fieldNamer) {
    if (field == null) {
      return new NoOpRecordAppender();
    }
    List<String> parts = Splitter.on(',').splitToList(field);
    if (parts.size() != 2) {
      throw new ConfigException(
          String.format("Could not parse %s for %s", field, EXTERNAL_KAFKA_METADATA));
    }
    String fieldName = fieldNamer.apply(parts.get(0));
    String fieldValue = parts.get(1);
    return new RecordAppender() {

      @Override
      public void addToSchema(SchemaBuilder builder) {
        builder.field(fieldName, Schema.STRING_SCHEMA);
      }

      @Override
      public void addToStruct(SinkRecord record, Struct struct) {
        struct.put(fieldName, fieldValue);
      }

      @Override
      public void addToMap(SinkRecord record, Map<String, Object> map) {

View on GitHub (pinned to 86d9c8fc54)