apache/beam · error · IllegalArgumentException

Unable to access MODEL$ field in SpecificRecordBase class

Error message

Unable to access MODEL$ field in SpecificRecordBase class

What it means

getGenericData(SpecificRecordBase) resolves the GenericData model associated with a generated Avro SpecificRecord. It first calls SpecificRecordBase.getSpecificData() (available since Avro 1.9); when that method is missing (NoSuchMethodError, Avro 1.8.2), it falls back to reflectively reading the static MODEL$ field. If reflection cannot access MODEL$ (the field was renamed, removed, or is not accessible), this IllegalArgumentException is thrown wrapping the IllegalAccessException.

Source

Thrown at sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroUtils.java:1778

   */
  private static org.apache.avro.Schema buildHiveLogicalTypeSchema(
      String hiveLogicalType, int size) {
    String schemaJson =
        String.format(
            "{\"type\": \"string\", \"logicalType\": \"%s\", \"maxLength\": %s}",
            hiveLogicalType, size);
    return new org.apache.avro.Schema.Parser().parse(schemaJson);
  }

  static GenericData getGenericData(SpecificRecordBase record) {
    try {
      return record.getSpecificData();
    } catch (NoSuchMethodError e) {
      try {
        // SpecificRecordBase.getSpecificData() was not available in avro 182
        return (GenericData) FieldUtils.readStaticField(record.getClass(), "MODEL$", true);
      } catch (IllegalAccessException ex) {
        throw new IllegalArgumentException(
            "Unable to access MODEL$ field in SpecificRecordBase class", ex);
      }
    }
  }

  private static <T> T checkRawType(
      Class<T> desiredRawType,
      Object value,
      LogicalType logicalType,
      Object rawType,
      Conversion<?> conversion,
      Class<?> convertedType) {
    String msg =
        String.format(
            "Value %s of class %s is not a supported type for logical type %s (%s). "
                + "Underlying avro built-in raw type should be instance of %s. "
                + "However it is instance of %s and has value %s ."
                + "Generic data has conversion %s, convertedType %s",

View on GitHub (pinned to 12126d8942)

Solutions

  1. Align Avro versions: ensure the generated SpecificRecord classes and the Beam pipeline use the same Avro version (>= 1.9 so getSpecificData() exists).
  2. Regenerate the SpecificRecord classes with the current avro-maven-plugin/avro-tools so MODEL$ and getSpecificData() are present and accessible.
  3. Check the classpath for duplicate/shaded Avro jars (mvn dependency:tree) and exclude the conflicting one.

Example fix

// before (pom.xml, mixed versions)
<dependency><groupId>org.apache.avro</groupId><artifactId>avro</artifactId><version>1.8.2</version></dependency>

// after
<dependency><groupId>org.apache.avro</groupId><artifactId>avro</artifactId><version>1.11.3</version></dependency>
Defensive patterns

Strategy: try-catch

Validate before calling

// fail fast at job setup
try {
  GenericData gd = AvroUtils.getGenericData(sampleSpecificRecord);
} catch (IllegalArgumentException e) {
  throw new IllegalStateException("Avro runtime version mismatch; align avro jars", e);
}

Try / catch

try {
  return AvroUtils.getGenericData(record);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("MODEL$")) {
    throw new IllegalStateException(
      "Generated class missing accessible MODEL$; regenerate with matching Avro version", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Using a generated Avro SpecificRecord class whose class hierarchy does not expose an accessible static MODEL$ field, while running with an Avro version where SpecificRecordBase.getSpecificData() is absent (e.g., 1.8.2) — the fallback FieldUtils.readStaticField(..., "MODEL$", true) then fails.

Common situations: Mixed Avro versions on the classpath (beam-sdks-java-extensions-avro compiled against one Avro version, generated classes compiled against another); generated classes from a custom codegen or a different Avro fork that omits MODEL$; shaded/relocated Avro where field names were obfuscated.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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