apache/beam · error · FileNotFoundException
The specified file does not exist: %s
Error message
The specified file does not exist: %s
What it means
GcsUtilV2.getBlob fetches a Blob via the com.google.cloud.storage.Storage client and throws FileNotFoundException when Storage.get returns null, i.e. the object does not exist (or the caller lacks visibility). StorageExceptions are translated separately.
Source
Thrown at sdks/java/extensions/google-cloud-platform-core/src/main/java/org/apache/beam/sdk/extensions/gcp/util/GcsUtilV2.java:129
case 404:
return new FileNotFoundException(e.getMessage());
case 409:
return new FileAlreadyExistsException(gcsPath.toString(), null, e.getMessage());
default:
return new IOException(e);
}
}
private IOException translateStorageException(
String bucketName, @Nullable String blobName, StorageException e) {
return translateStorageException(GcsPath.fromComponents(bucketName, blobName), e);
}
public Blob getBlob(GcsPath gcsPath, BlobGetOption... options) throws IOException {
try {
Blob blob = storage.get(gcsPath.getBucket(), gcsPath.getObject(), options);
if (blob == null) {
throw new FileNotFoundException(
String.format("The specified file does not exist: %s", gcsPath.toString()));
}
return blob;
} catch (StorageException e) {
throw translateStorageException(gcsPath, e);
}
}
public long fileSize(GcsPath gcsPath) throws IOException {
return getBlob(gcsPath, BlobGetOption.fields(BlobField.SIZE)).getSize();
}
/** A class that holds either a {@link Blob} or an {@link IOException}. */
@AutoValue
public abstract static class BlobResult {
/** Returns the {@link Blob}. */
public abstract @Nullable Blob blob();View on GitHub (pinned to 12126d8942)
Solutions
- Verify the gs:// path exists: gsutil ls <path> or storage.get via console.
- Check the file path/template configuration for typos or stale values.
- Guard with gcsUtil.expand/gcsUtil.treeList over a directory pattern before calling fileSize/getBlob.
- Handle FileNotFoundException at the call site when the file is optional.
Example fix
// before
long size = gcsUtil.fileSize(GcsPath.fromUri(path));
// after
try {
long size = gcsUtil.fileSize(GcsPath.fromUri(path));
} catch (FileNotFoundException e) {
LOG.warn("Skipping missing object {}", path);
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check existence via listing
List<Metadata> existing = gcsUtil.expand(GcsPath.fromUri(dirPattern));
boolean present = existing.stream()
.anyMatch(m -> m.resourceId().toString().equals(path.toString())); Try / catch
try {
Blob blob = gcsUtil.getBlob(GcsPath.fromUri(uri));
} catch (FileNotFoundException e) {
// treat as missing: skip, substitute default, or surface config error
} Prevention
- Resolve file paths from fresh directory listings instead of stale cached values
- Validate templated path options before pipeline start
- Use expand()/match() on globs rather than calling fileSize on possibly-absent exact paths
When it happens
Trigger: Any call path through getBlob — fileSize(gcsPath), expand(gcsPath), or blob(...) — where the (bucket, object) pair does not exist, e.g. wrong object path, object deleted, or getBlob called before a write completes.
Common situations: Stale file listing cached by a caller; typos or wrong templated file paths in pipeline options; eventual consistency windows in listing vs. get in concurrent writes; reading a match-generated path that matched zero files is guarded elsewhere but direct paths can 404.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- File spec %s not found
- Could not find file %s
- Error completing file copies with retries, sample: from %s t
- Interrupted backoff of file copies with retries, sample: fro
- Skipping dest existence is only supported within a bucket.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/766bea8a7bc875d9.
Report an issue: GitHub.