{"record":{"id":"092a685e2fe873de","repo":"apache/hadoop","slug":"can-t-write-instance-as-declaredclass","errorCode":null,"errorMessage":"Can't write: {instance} as {declaredClass}","messagePattern":"Can't write: (.+?) as (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/ObjectWritable.java","lineNumber":232,"sourceCode":"      } else if (declaredClass == Float.TYPE) {   // float\n        out.writeFloat(((Float)instance).floatValue());\n      } else if (declaredClass == Double.TYPE) {  // double\n        out.writeDouble(((Double)instance).doubleValue());\n      } else if (declaredClass == Void.TYPE) {    // void\n      } else {\n        throw new IllegalArgumentException(\"Not a primitive: \"+declaredClass);\n      }\n    } else if (declaredClass.isEnum()) {         // enum\n      UTF8.writeString(out, ((Enum)instance).name());\n    } else if (Writable.class.isAssignableFrom(declaredClass)) { // Writable\n      UTF8.writeString(out, instance.getClass().getName());\n      ((Writable)instance).write(out);\n\n    } else if (Message.class.isAssignableFrom(declaredClass)) {\n      ((Message)instance).writeDelimitedTo(\n          DataOutputOutputStream.constructOutputStream(out));\n    } else {\n      throw new IOException(\"Can't write: \"+instance+\" as \"+declaredClass);\n    }\n  }\n  \n  \n  /**\n   * Read a {@link Writable}, {@link String}, primitive type, or an array of\n   * the preceding.\n   *\n   * @param conf configuration.\n   * @param in DataInput.\n   * @return Object.\n   * @throws IOException raised on errors performing I/O.\n   */\n  public static Object readObject(DataInput in, Configuration conf)\n    throws IOException {\n    return readObject(in, null, conf);\n  }\n    ","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/ObjectWritable.java#L214-L250","documentation":"Thrown by ObjectWritable.writeObject when the instance's declared class is a reference type that none of the supported branches handle: not a String, enum, Writable, protobuf Message, array, or NullInstance. ObjectWritable is a closed serialization framework — it cannot magically serialize arbitrary Java objects, so an unsupported POJO falls through to this IOException naming the instance and declared class.","triggerScenarios":"writeObject(out, new MyPojo(...), MyPojo.class, conf) where MyPojo implements none of the supported interfaces; putting a custom business object into an RPC method parameter or Writable field serialized via ObjectWritable without making it Writable.","commonSituations":"Adding a new field/parameter type to an RPC protocol that uses ObjectWritable and forgetting to implement Writable; migrating plain POJOs into Hadoop RPC paths; third-party classes that cannot be modified showing up in serialized data.","solutions":["Implement Writable (write/readFields) on the class — the most common fix — and keep declaring it as itself.","Convert to a protobuf Message if the pipeline is protobuf-oriented.","If the class cannot be modified, wrap it: store a serialized form (e.g. JSON/bytes in a Text or BytesWritable) instead of the raw object.","For simple values, use String or a boxed primitive representation."],"exampleFix":"// before: plain POJO — ObjectWritable cannot serialize it\nclass Point { int x, y; }\nObjectWritable.writeObject(out, new Point(), Point.class, conf); // throws\n\n// after: make the class Writable\nclass Point implements Writable {\n  int x, y;\n  public void write(DataOutput out) throws IOException { out.writeInt(x); out.writeInt(y); }\n  public void readFields(DataInput in) throws IOException { x = in.readInt(); y = in.readInt(); }\n}\nObjectWritable.writeObject(out, new Point(), Point.class, conf);","handlingStrategy":"type-guard","validationCode":"if (!(instance instanceof Writable)\n     && !(instance instanceof String)\n     && !(instance instanceof Enum)\n     && !(instance instanceof com.google.protobuf.Message)\n     && !instance.getClass().isArray()) {\n  throw new IllegalArgumentException(\n      \"Type \" + instance.getClass() + \" is not serializable by ObjectWritable\");\n}\nObjectWritable.writeObject(out, instance, declaredClass, conf);","typeGuard":"static boolean isObjectWritableSerializable(Object o) {\n  return o == null\n      || o instanceof Writable\n      || o instanceof String\n      || o instanceof Enum\n      || o instanceof com.google.protobuf.Message\n      || o.getClass().isArray();\n}","tryCatchPattern":"try {\n  ObjectWritable.writeObject(out, instance, declaredClass, conf);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Can't write\")) {\n    throw new IllegalStateException(\"Class \" + instance.getClass()\n        + \" must implement Writable (or be String/enum/protobuf Message) \"\n        + \"to cross ObjectWritable\", e);\n  }\n  throw e;\n}","preventionTips":["Make every custom type in RPC/data paths implement Writable from day one.","For third-party classes you can't modify, wrap their state in Text/BytesWritable (e.g. JSON).","Add a compile-time convention check or ArchUnit rule: no type enters ObjectWritable unless Writable/enum/String/Message/array."],"tags":["serialization","object-writable","writable","rpc","hadoop-common"],"backgroundTag":"unsupported-type-serialization","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}