apache/hadoop · error · RuntimeException
Object %s doesn't exit
Error message
Object %s doesn't exit
What it means
TOS.get(key, offset, limit) special-cases limit == 0: a zero-byte range GET would not reveal whether the object exists, so it calls head(key) instead; if the object does not exist it throws RuntimeException("Object <key> doesn't exit") (the message contains a typo of 'exist'). A zero-length read of a missing object is thereby converted into a not-found error.
Source
Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/tos/TOS.java:252
this.client = client;
}
private void checkAvailableClient() {
Preconditions.checkState(client != null,
"Encountered uninitialized ObjectStorage, call initialize(..) please.");
}
@Override
public ObjectContent get(String key, long offset, long limit) {
checkAvailableClient();
Preconditions.checkArgument(offset >= 0, "offset is a negative number: %s", offset);
if (limit == 0) {
// Can not return empty stream when limit = 0, because the requested object might not exist.
if (head(key) != null) {
return new ObjectContent(Constants.MAGIC_CHECKSUM, EMPTY_STREAM);
} else {
throw new RuntimeException(String.format("Object %s doesn't exit", key));
}
}
long end = limit < 0 ? -1 : offset + limit - 1;
GetObjectFactory factory = (k, startOff, endOff) -> getObject(key, startOff, endOff);
ChainTOSInputStream chainStream =
new ChainTOSInputStream(factory, key, offset, end, maxDrainBytes, maxInputStreamRetries);
return new ObjectContent(chainStream.checksum(), chainStream);
}
@Override
public Iterable<ObjectInfo> listDir(String key, boolean recursive) {
if (recursive) {
if (bucket().isDirectory()) {
// The directory bucket only support list object with delimiter = '/', so if we want to
// list directory recursively, we have to list each dir step by step.
return bfsListDir(key);
} else {View on GitHub (pinned to 2add963021)
Solutions
- Check objectStatus/head(key) before get(key, offset, 0) and handle a null result
- Catch this RuntimeException and map it to FileNotFoundException for proper Hadoop semantics
- Remove the concurrent delete/read race, or accept the failure as a benign not-found signal
Example fix
// before
ObjectContent c = storage.get(key, 0, 0);
// after
if (storage.head(key) == null) {
throw new FileNotFoundException(key);
}
ObjectContent c = storage.get(key, 0, 0); Defensive patterns
Strategy: validation
Validate before calling
if (storage.head(key) == null) {
throw new FileNotFoundException(key);
}
ObjectContent c = storage.get(key, offset, 0); Try / catch
try {
return storage.get(key, 0, 0);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("doesn't exit")) {
throw (FileNotFoundException) new FileNotFoundException(key).initCause(e);
}
throw e;
} Prevention
- head() before zero-length reads
- Eliminate concurrent delete/read races on the same key
- Map this RuntimeException to FileNotFoundException for Hadoop-correct semantics
When it happens
Trigger: Reading an object with limit 0 — e.g. an empty-file read or a length-0 verification — when the key does not exist: deleted concurrently, wrong key/prefix, or a key that was never written.
Common situations: A concurrent delete racing a zero-length read; stale file-status caches claiming a file exists after removal; keys assembled with the wrong prefix or encoding.
Related errors
- Not supported
- tos: request interrupted.
- Expected checksum is %s while actual checksum is %s
- %s is not appendable because append non-existed object with
- %s is not appendable.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/26699b9f6ecb7f5e.
Report an issue: GitHub.