apache/druid · error · IllegalStateException

Value overrun

Error message

Value overrun

What it means

addStringsToList decodes a string (or string array) field from the frame's memory, walking bytes until a VALUE_TERMINATOR. If a non-null value starts but the field's limit is reached before the terminator, the physical encoding is truncated or corrupted beyond the expected region, so "Value overrun" is thrown. This indicates frame corruption or reading past the field's declared bounds.

Solutions

  1. Verify the frame file/bytes are complete and uncorrupted (re-run the query or re-fetch the frame).
  2. Ensure the writer and reader Druid versions match for frame serialization.
  3. Check that the position/limit passed to the reader come from the frame's own field boundaries, not manual arithmetic.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  reader.readStringsFromMemory(memory, position, limit, list);
} catch (IllegalStateException e) {
  if (e.getMessage().contains("Value overrun")) {
    throw new CorruptFrameException("Frame data truncated; regenerate frame", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Reading a frame whose string field bytes are truncated (e.g. frame buffer cut short, wrong limit passed to readStringsFromMemory), so a NOT_NULL_BYTE is seen but no VALUE_TERMINATOR exists before limit.

Common situations: Frames written by a bugged or mismatched Druid version being read by a different version (serialization change); corrupted on-disk/durable-storage frame files; incorrect offset arithmetic in custom code reading raw frame memory.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/3a1362fcb6d4325d. Report an issue: GitHub.

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/frame/field/StringFieldReader.java:579

            isEffectivelyNull = true;
          }

          // Skip; next byte will be a null/not-null byte or a row terminator.
          break;

        case StringFieldWriter.ROW_TERMINATOR:
          // Skip; this is the end of the row, so we'll fall through to the return statement.
          rowTerminatorSeen = true;
          break;

        case StringFieldWriter.NULL_BYTE:
          list.add(null);
          break;

        case StringFieldWriter.NOT_NULL_BYTE:
          for (long i = position; ; i++) {
            if (i >= limit) {
              throw new ISE("Value overrun");
            }

            final byte b = memory.getByte(i);

            if (b == StringFieldWriter.VALUE_TERMINATOR) {
              final int len = Ints.checkedCast(i - position);

              final ByteBuffer buf = FrameReaderUtils.readByteBuffer(memory, position, len);
              list.add(buf);

              position += len;

              break;
            }
          }

          break;

View on GitHub (pinned to 9b90983fd2)