apache/beam · error · IllegalStateException

Metadata value type must be one of String, Long, or byte[]…

Error message

Metadata value type must be one of String, Long, or byte[]. Found ${v.getClass().getSimpleName()}

What it means

When writing Avro container files through AvroIO.Write, user metadata values may only be String, Long, or byte[] — the types Avro's DataFileWriter.setMeta supports. Any other value type throws IllegalStateException at write setup time.

Solutions

  1. Convert numeric metadata values to Long explicitly ((long) intValue)
  2. Convert boolean/double values to String or byte[] before passing
  3. Whitelist/transform the metadata map at pipeline construction to the three supported types

Example fix

// before
metadata.put("count", 42);            // Integer
// after
metadata.put("count", 42L);           // Long
Defensive patterns

Strategy: type-guard

Validate before calling

metadata.values().forEach(v -> {
  if (!(v instanceof String || v instanceof Long || v instanceof byte[]))
    throw new IllegalArgumentException("Bad metadata type: " + v.getClass());
});

Type guard

static boolean isAvroMetaType(Object v) {
  return v instanceof String || v instanceof Long || v instanceof byte[];
}

Try / catch

try { writer.create(schema, out); } catch (IllegalStateException e) { /* normalize metadata and retry */ }

Prevention

When it happens

Trigger: Passing a Map<String, Object> with metadata (withMetadata) whose values are e.g. Integer, Double, Boolean, or Float to AvroIO.Write.

Common situations: Auto-boxed ints from Java literals (Integer instead of Long), JSON-parsed metadata with mixed types, or configuration maps built generically without normalizing types.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/706e20e64bb2efde. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/io/AvroIO.java:2179

      if (getRecordFormatter() != null) {
        datumWriter = new FormattedDatumWriter<>(schema, getRecordFormatter());
      } else if (getDatumWriterFactory() != null) {
        datumWriter = getDatumWriterFactory().apply(schema);
      } else {
        datumWriter = new ReflectDatumWriter<>(schema);
      }
      writer = new DataFileWriter<>(datumWriter);
      writer.setCodec(getCodec().getCodec());
      for (Map.Entry<String, Object> entry : getMetadata().entrySet()) {
        Object v = entry.getValue();
        if (v instanceof String) {
          writer.setMeta(entry.getKey(), (String) v);
        } else if (v instanceof Long) {
          writer.setMeta(entry.getKey(), (Long) v);
        } else if (v instanceof byte[]) {
          writer.setMeta(entry.getKey(), (byte[]) v);
        } else {
          throw new IllegalStateException(
              "Metadata value type must be one of String, Long, or byte[]. Found "
                  + v.getClass().getSimpleName());
        }
      }
      writer.create(schema, Channels.newOutputStream(channel));
    }

    @Override
    public void write(ElementT element) throws IOException {
      writer.append(element);
    }

    @Override
    public void flush() throws IOException {
      writer.flush();
    }
  }

View on GitHub (pinned to 12126d8942)