apache/hadoop · error · IOException

wrong value class: {} is not {}

Error message

wrong value class: {} is not {}

What it means

The value-side twin of the key check in Writer.append: val.getClass() must be exactly (==) the declared valClass or append throws this IOException naming both classes. The check is per record, so a single bad value stops the write before the record header is emitted.

Source

Thrown at hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/io/SequenceFile.java:1476

    public void append(Writable key, Writable val)
      throws IOException {
      append((Object) key, (Object) val);
    }

    /**
     * Append a key/value pair.
     * @param key input Object key.
     * @param val input Object val.
     * @throws IOException raised on errors performing I/O.
     */
    @SuppressWarnings("unchecked")
    public synchronized void append(Object key, Object val)
      throws IOException {
      if (key.getClass() != keyClass)
        throw new IOException("wrong key class: "+key.getClass().getName()
                              +" is not "+keyClass);
      if (val.getClass() != valClass)
        throw new IOException("wrong value class: "+val.getClass().getName()
                              +" is not "+valClass);

      buffer.reset();

      // Append the 'key'
      keySerializer.serialize(key);
      int keyLength = buffer.getLength();
      if (keyLength < 0)
        throw new IOException("negative length keys not allowed: " + key);

      // Append the 'value'
      if (compress == CompressionType.RECORD) {
        deflateFilter.resetState();
        compressedValSerializer.serialize(val);
        deflateOut.flush();
        deflateFilter.finish();
      } else {
        uncompressedValSerializer.serialize(val);

View on GitHub (pinned to 2add963021)

Solutions

  1. Match Writer.valueClass(...) to the concrete appended type
  2. Convert or copy subclass values into the exact declared type before append
  3. Add a guard: val.getClass() == writer.getValueClass() before each append in generic plumbing

Example fix

// before
Writer w = SequenceFile.createWriter(conf, Writer.file(p),
    Writer.keyClass(Text.class), Writer.valueClass(IntWritable.class));
w.append(new Text("k"), new Text("not-an-int")); // wrong value class

// after
w.append(new Text("k"), new IntWritable(7));
Defensive patterns

Strategy: type-guard

Validate before calling

if (val.getClass() != w.getValueClass()) {
  throw new IllegalArgumentException("value " + val.getClass() + " != declared " + w.getValueClass());
}

Type guard

static boolean isExactValueClass(SequenceFile.Writer w, Object val) {
  return val != null && val.getClass() == w.getValueClass();
}

Try / catch

try {
  w.append(key, val);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("wrong value class")) {
    // value type drift: convert to the declared class or recreate the writer
  } else { throw e; }
}

Prevention

When it happens

Trigger: Appending a value whose concrete class differs from Writer.valueClass(...): a subclass instance, a type from another library version, or null-ish placeholders with the wrong type after refactoring.

Common situations: Value schema changed in code but not in the writer options; mixed collections feeding append with heterogeneous elements; copy-paste writers reused across data types.

Related errors


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