apache/hadoop · error · IllegalArgumentException

Not a primitive: {declaredClass}

Error message

Not a primitive: {declaredClass}

What it means

Thrown by ObjectWritable.writeObject when declaredClass.isPrimitive() is true but the class matches none of the handled TYPE constants (Boolean, Byte, Character, Short, Integer, Long, Float, Double, Void). It is the terminal else of the primitive-dispatch chain: the declared class claimed to be a primitive yet was not one this serializer knows how to emit, which on a standard JVM indicates corrupted state or an exotic class object rather than a normal data problem.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/ObjectWritable.java:220

      if (declaredClass == Boolean.TYPE) {        // boolean
        out.writeBoolean(((Boolean)instance).booleanValue());
      } else if (declaredClass == Character.TYPE) { // char
        out.writeChar(((Character)instance).charValue());
      } else if (declaredClass == Byte.TYPE) {    // byte
        out.writeByte(((Byte)instance).byteValue());
      } else if (declaredClass == Short.TYPE) {   // short
        out.writeShort(((Short)instance).shortValue());
      } else if (declaredClass == Integer.TYPE) { // int
        out.writeInt(((Integer)instance).intValue());
      } else if (declaredClass == Long.TYPE) {    // long
        out.writeLong(((Long)instance).longValue());
      } else if (declaredClass == Float.TYPE) {   // float
        out.writeFloat(((Float)instance).floatValue());
      } else if (declaredClass == Double.TYPE) {  // double
        out.writeDouble(((Double)instance).doubleValue());
      } else if (declaredClass == Void.TYPE) {    // void
      } else {
        throw new IllegalArgumentException("Not a primitive: "+declaredClass);
      }
    } else if (declaredClass.isEnum()) {         // enum
      UTF8.writeString(out, ((Enum)instance).name());
    } else if (Writable.class.isAssignableFrom(declaredClass)) { // Writable
      UTF8.writeString(out, instance.getClass().getName());
      ((Writable)instance).write(out);

    } else if (Message.class.isAssignableFrom(declaredClass)) {
      ((Message)instance).writeDelimitedTo(
          DataOutputOutputStream.constructOutputStream(out));
    } else {
      throw new IOException("Can't write: "+instance+" as "+declaredClass);
    }
  }
  
  
  /**
   * Read a {@link Writable}, {@link String}, primitive type, or an array of

View on GitHub (pinned to 2add963021)

Solutions

  1. Log declaredClass.getName() at the throw site to identify which bogus Class value is flowing in.
  2. Fix how declaredClass is derived — it must be one of the eight primitive TYPE constants or one of the supported reference types (String, enum, Writable, protobuf Message, arrays).
  3. If the value is a wrapper object and you don't need primitive encoding, pass the wrapper class (Integer.class) instead of Integer.TYPE.

Example fix

// before: wrong field type object routed into ObjectWritable
Object o = 7;
Class<?> c = int.class; // handled, but suppose c came from a buggy lookup returning a fake primitive
ObjectWritable.writeObject(out, o, c, conf);

// after: validate the declared class against supported primitives up front
if (c.isPrimitive() && !SUPPORTED_PRIMITIVES.contains(c)) {
  throw new IllegalArgumentException("Unsupported declared class: " + c);
}
ObjectWritable.writeObject(out, o, c, conf);
Defensive patterns

Strategy: type-guard

Validate before calling

private static final Set<Class<?>> SUPPORTED = new HashSet<>(Arrays.asList(
    Boolean.TYPE, Byte.TYPE, Character.TYPE, Short.TYPE, Integer.TYPE,
    Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE));
if (declaredClass.isPrimitive() && !SUPPORTED.contains(declaredClass)) {
  throw new IllegalArgumentException("Unsupported declared class " + declaredClass);
}

Type guard

static boolean isObjectWritablePrimitive(Class<?> c) {
  return c == Boolean.TYPE || c == Byte.TYPE || c == Character.TYPE
      || c == Short.TYPE || c == Integer.TYPE || c == Long.TYPE
      || c == Float.TYPE || c == Double.TYPE || c == Void.TYPE;
}

Prevention

When it happens

Trigger: Calling writeObject(out, instance, declaredClass, conf) with a Class object whose isPrimitive() lies or with a pseudo-primitive from a non-standard JVM/language runtime; more practically, reaching this branch through a bug where declaredClass was computed wrongly (e.g. getClass() vs field type mix-ups in RPC parameter serialization).

Common situations: Hand-rolled RPC/serialization code using ObjectWritable for generic fields; cross-language or bytecode-manipulation runtimes that produce nonstandard primitive Class objects; regressions after refactoring reflection code that derives declaredClass.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/abfcf78252d603a7. Report an issue: GitHub.