apache/hadoop · error · FileNotFoundException
Item not found: %s
Error message
Item not found: %s
What it means
The client read channel's static validate(itemInfo) throws FileNotFoundException("Item not found: <resourceId>") when opening a channel for an object whose GoogleCloudStorageItemInfo.exists() is false. It first asserts the id is a storage object (not a bucket or root). This runs at open time, before any bytes are requested.
Source
Thrown at hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorageClientReadChannel.java:569
blobReadOptions.add(BlobSourceOption.generationMatch(blobId.getGeneration()));
}
// TODO: Add support for encryptionKey
return blobReadOptions.toArray(new BlobSourceOption[blobReadOptions.size()]);
}
private boolean isFooterRead() {
return objectSize - currentPosition <= config.getMinRangeRequestSize();
}
}
private static void validate(GoogleCloudStorageItemInfo itemInfo) throws IOException {
checkNotNull(itemInfo, "itemInfo cannot be null");
StorageResourceId resourceId = itemInfo.getResourceId();
checkArgument(
resourceId.isStorageObject(), "Can not open a non-file object for read: %s", resourceId);
if (!itemInfo.exists()) {
throw new FileNotFoundException(String.format("Item not found: %s", resourceId));
}
}
private IOException convertError(Exception error) {
String msg = String.format("Error reading '%s'", resourceId);
switch (ErrorTypeExtractor.getErrorType(error)) {
case NOT_FOUND:
return createFileNotFoundException(
resourceId.getBucketName(), resourceId.getObjectName(), new IOException(msg, error));
case OUT_OF_RANGE:
return (IOException) new EOFException(msg).initCause(error);
default:
return new IOException(msg, error);
}
}
/** Validates that the given position is valid for this channel. */
private void validatePosition(long position) throws IOException {View on GitHub (pinned to 2add963021)
Solutions
- Re-stat the path with getItemInfo immediately before opening and handle absence in application logic.
- For rename/commit races, use an idempotent output committer and serialize producer/cleanup of the same paths.
- If pinning generations intentionally, catch FileNotFoundException and re-fetch item info for the live generation.
- Fix path construction (URI encoding, leading slashes, case).
Example fix
// before
try (SeekableByteChannel ch = gcs.open(itemInfo)) { ... } // FileNotFoundException
// after
GoogleCloudStorageItemInfo fresh = gcs.getItemInfo(itemInfo.getResourceId());
if (!fresh.exists()) {
return; // or throw domain-specific 'input vanished' error
}
try (SeekableByteChannel ch = gcs.open(fresh)) { ... } Defensive patterns
Strategy: validation
Validate before calling
GoogleCloudStorageItemInfo fresh = gcs.getItemInfo(resourceId);
if (!fresh.exists()) {
throw new MissingInputException(resourceId); // domain-specific, actionable
}
try (SeekableByteChannel ch = gcs.open(fresh)) { /* read */ } Try / catch
catch (FileNotFoundException e) {
// input vanished (deleted/moved concurrently): re-stat to distinguish typo vs race
if (!gcs.getItemInfo(resourceId).exists()) throw e;
/* else stale info: retry open with fresh item info */
} Prevention
- Stat with getItemInfo immediately before open instead of trusting cached listings.
- Give each path a single owner (producer or deleter) to avoid delete/read races.
- Surface file-not-found with the full gs:// URI so path typos are easy to spot.
When it happens
Trigger: gcs.open(itemInfo) / GHFS open() on a path that was deleted, never existed, or whose pinned generation no longer exists; opening from itemInfo taken from a stale listing or cache after the object was removed.
Common situations: Races between concurrent jobs (output committer cleanup deleting temp files while another task reads them); stale directory listings; typo'd or wrongly-encoded paths; objects deleted and recreated while a reader pinned the old generation.
Related errors
- Item not found: %s
- Received end of stream result before all requestedBytes were
- Unable to update the boundaries/Range of contentChannel %s
- Multipart upload incomplete: expected {} parts but got {}
- Can't make directory for path: %s, since it is a file.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/5e1d1f6af9dc2d1a.
Report an issue: GitHub.