apache/beam · error · CoderException

NullableCoder expects either a byte valued 0 (null) or 1 (pr

Error message

NullableCoder expects either a byte valued 0 (null) or 1 (present), got %s

What it means

NullableCoder's decode() reads one byte that must be 0 (ENCODE_NULL) or 1 (ENCODE_PRESENT). Any other value means the stream is corrupt, truncated, or was not written by NullableCoder, so decoding cannot proceed. This is a data-integrity failure, not an application-logic error.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/coders/NullableCoder.java:89

    } else {
      outStream.write(ENCODE_PRESENT);
      valueCoder.encode(value, outStream, context);
    }
  }

  @Override
  public @Nullable T decode(InputStream inStream) throws IOException, CoderException {
    return decode(inStream, Context.NESTED);
  }

  @Override
  public @Nullable T decode(InputStream inStream, Context context)
      throws IOException, CoderException {
    int b = inStream.read();
    if (b == ENCODE_NULL) {
      return null;
    } else if (b != ENCODE_PRESENT) {
      throw new CoderException(
          String.format(
              "NullableCoder expects either a byte valued %s (null) or %s (present), got %s",
              ENCODE_NULL, ENCODE_PRESENT, b));
    }
    return valueCoder.decode(inStream, context);
  }

  @Override
  public List<Coder<T>> getCoderArguments() {
    return ImmutableList.of(valueCoder);
  }

  /**
   * {@code NullableCoder} is deterministic if the nested {@code Coder} is.
   *
   * <p>{@inheritDoc}
   */
  @Override

View on GitHub (pinned to 12126d8942)

Solutions

  1. Re-run the pipeline from a source rather than resuming from state encoded with an incompatible coder version
  2. Verify the InputStream is positioned exactly at the start of the NullableCoder-encoded value (no earlier fields were skipped)
  3. Check that the writer and reader use the same coder version (same Beam release for state/backup data)

Example fix

// before
Coder<T> coder = myCoder; // changed from NullableCoder.of(...), old state unreadable
// after
// re-run pipeline from source, or keep the same coder:
Coder<T> coder = NullableCoder.of(innerCoder); // matches previously written bytes
Defensive patterns

Strategy: try-catch

Validate before calling

// No pre-call check possible on a raw stream; verify the coder matches the writer's coder version

Type guard

null

Try / catch

try { T v = nullableCoder.decode(in, Context.OUTER); } catch (CoderException e) { /* treat stream as corrupt: re-read from source */ }

Prevention

When it happens

Trigger: Decoding a byte stream whose first byte is not 0x00 or 0x01: e.g. stream produced by a different coder, an out-of-sync InputStream offset, byte corruption, or version mismatch between writer and reader coder.

Common situations: Changing a pipeline's coder (e.g. adding/removing NullableCoder) without re-running from scratch, so old checkpoints/state are decoded with the new coder; byte-stream truncation; manual wire-format fiddling.

Related errors


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