apache/hadoop · error · IOException
Not an OOB status: {}
Error message
Not an OOB status: {} What it means
getOOBTimeout maps an out-of-band pipeline Status (the numeric range Status.OOB_RESTART_VALUE..Status.OOB_RESERVED3_VALUE) to its ack/mirror timeout slot in oobTimeouts. Passing any ordinary Status (SUCCESS, ERROR, CHECKSUM_OK, ...) is a programming error: those have no OOB timeout, so the call is rejected before indexing the array.
Source
Thrown at hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java:4208
oobTimeouts = new long[numOobTypes];
final String[] ele = getConf().get(DFS_DATANODE_OOB_TIMEOUT_KEY,
DFS_DATANODE_OOB_TIMEOUT_DEFAULT).split(",");
for (int i = 0; i < numOobTypes; i++) {
oobTimeouts[i] = (i < ele.length) ? Long.parseLong(ele[i]) : 0;
}
}
/**
* Get the timeout to be used for transmitting the OOB type
* @return the timeout in milliseconds
*/
public long getOOBTimeout(Status status)
throws IOException {
if (status.getNumber() < Status.OOB_RESTART_VALUE ||
status.getNumber() > Status.OOB_RESERVED3_VALUE) {
// Not an OOB.
throw new IOException("Not an OOB status: " + status);
}
return oobTimeouts[status.getNumber() - Status.OOB_RESTART_VALUE];
}
/**
* Start a timer to periodically write DataNode metrics to the log file. This
* behavior can be disabled by configuration.
*
*/
protected void startMetricsLogger() {
long metricsLoggerPeriodSec = getConf().getInt(
DFS_DATANODE_METRICS_LOGGER_PERIOD_SECONDS_KEY,
DFS_DATANODE_METRICS_LOGGER_PERIOD_SECONDS_DEFAULT);
if (metricsLoggerPeriodSec <= 0) {
return;
}View on GitHub (pinned to 2add963021)
Solutions
- Check the numeric range before calling: status.getNumber() >= Status.OOB_RESTART_VALUE && status.getNumber() <= Status.OOB_RESERVED3_VALUE
- Pass only the dedicated OOB constants (Status.OOB_RESTART, OOB_SOFT_CAPACITY, ...) to getOOBTimeout
- Branch in pipeline code: OOB statuses -> getOOBTimeout; all others -> normal ack timeout
Example fix
// before
long timeout = datanode.getOOBTimeout(ack.getStatus()); // throws for SUCCESS/ERROR/etc.
// after
Status s = ack.getStatus();
long timeout;
if (s.getNumber() >= Status.OOB_RESTART_VALUE
&& s.getNumber() <= Status.OOB_RESERVED3_VALUE) {
timeout = datanode.getOOBTimeout(s);
} else {
timeout = normalAckTimeoutMs; // ordinary ack path
} Defensive patterns
Strategy: validation
Validate before calling
boolean isOob = status.getNumber() >= Status.OOB_RESTART_VALUE
&& status.getNumber() <= Status.OOB_RESERVED3_VALUE;
if (isOob) {
long timeout = datanode.getOOBTimeout(status);
} else {
// ordinary status: use the normal ack timeout, never getOOBTimeout
} Type guard
// Java predicate acting as a type guard over the Status enum range
static boolean isOobStatus(Status s) {
return s != null
&& s.getNumber() >= Status.OOB_RESTART_VALUE
&& s.getNumber() <= Status.OOB_RESERVED3_VALUE;
} Prevention
- Only pass the documented OOB constants (OOB_RESTART, OOB_SOFT_CAPACITY, ...) to getOOBTimeout
- Centralize the OOB range check in one helper next to your ack-handling code
- Add unit tests feeding every Status value through the branch to catch new enum constants
When it happens
Trigger: Calling DataNode.getOOBTimeout(status) with a non-OOB status - typically packet-ack handling code that forwards an arbitrary client/NN Status without first checking the OOB numeric range.
Common situations: Custom or modified DataTransfer pipeline code; newer Hadoop versions adding Status constants that old branching code does not recognize; copied code assuming every status is OOB.
Related errors
- dfs.datanode.parallel.volumes.load.threads.num = {} < 1
- Path part {s} from URI {p} is not a valid filename.
- Offset {startOffset} and length {length} don't match block
- Not a valid Boolean value for {property} in reconfSlowPeerPa
- FsDatasetSpi has not been initialized
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/b67a97ac4b42fa9c.
Report an issue: GitHub.