@google-cloud/storage
>=5.0.0postconditions51functions20last verified2026-06-24coverage score87%Postconditions: what we check
- upload · upload-network-errorerrorWhenNetwork connection fails or times outThrows
ApiError with code ECONNRESET, ETIMEDOUT, or HTTP 408/504Required handlingCaller MUST wrap bucket.upload() in try-catch block. Network errors can occur due to internet connectivity issues, DNS failures, or Cloud Storage service downtime. The library automatically retries (default: 3 attempts with exponential backoff), but will throw after max retries exhausted.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - upload · upload-permission-errorerrorWhenIAM permissions insufficient for bucket writeThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.create permission on the target bucket. This error is NOT automatically retried.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - upload · upload-bucket-not-founderrorWhenBucket does not existThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller MUST handle bucket not found errors. Create bucket first using storage.createBucket() or verify bucket name is correct.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3] - upload · upload-file-not-founderrorWhenLocal file path does not existThrows
Error: ENOENT: no such file or directoryRequired handlingCaller MUST validate local file exists before calling upload(). Check with fs.existsSync() or handle file not found errors gracefully.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - download · download-file-not-founderrorWhenFile does not exist in bucketThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller MUST handle file not found errors. Check if file exists using file.exists() before downloading, or handle 404 gracefully.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - download · download-permission-errorerrorWhenIAM permissions insufficient for file readThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.get permission. This error is NOT automatically retried.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - download · download-network-errorerrorWhenNetwork connection fails during downloadThrows
ApiError with code ECONNRESET, ETIMEDOUTRequired handlingCaller MUST handle network errors. Large file downloads are more susceptible to connection timeouts. The library automatically retries, but will throw after max retries exhausted.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5] - download · download-corruption-errorerrorWhenDownloaded file hash does not match expected checksumThrows
Error with code CONTENT_DOWNLOAD_MISMATCHRequired handlingCaller MUST retry download when corruption detected. This error indicates the downloaded content differs from what was stored. Retry the download operation.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[6] - delete · delete-not-founderrorWhenFile or bucket does not existThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller SHOULD handle 404 errors gracefully. If idempotent delete is desired, catch 404 and treat as success. Otherwise, throw error to caller.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[7] - delete · delete-permission-errorerrorWhenIAM permissions insufficient for deleteThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.delete or storage.buckets.delete permission.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[7] - delete · delete-bucket-not-emptyerrorWhenAttempting to delete bucket that contains filesThrows
ApiError with HTTP 409 ConflictRequired handlingCaller MUST delete all files first using bucket.deleteFiles() before deleting bucket, or handle conflict error.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[8] - save · save-permission-errorerrorWhenIAM permissions insufficient for file writeThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.create permission on the target bucket.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - save · save-network-errorerrorWhenNetwork connection fails during writeThrows
ApiError with code ECONNRESET, ETIMEDOUTRequired handlingCaller MUST handle network errors. The library automatically retries with exponential backoff, but will throw after max retries exhausted.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[9] - getMetadata · getmetadata-not-founderrorWhenFile or bucket does not existThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller MUST handle not found errors. Check if resource exists using exists() method before calling getMetadata(), or handle 404 gracefully.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[10] - getMetadata · getmetadata-permission-errorerrorWhenIAM permissions insufficient for metadata readThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has appropriate read permissions for the resource.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[10] - setMetadata · setmetadata-not-founderrorWhenFile or bucket does not existThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller MUST handle not found errors. Verify resource exists before attempting to update metadata.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[11] - setMetadata · setmetadata-permission-errorerrorWhenIAM permissions insufficient for metadata writeThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.update or storage.buckets.update permission.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[11] - getFiles · getfiles-permission-errorerrorWhenIAM permissions insufficient for listingThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.list permission on the bucket.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - getFiles · getfiles-network-errorerrorWhenNetwork connection failsThrows
ApiError with network error codesRequired handlingCaller MUST handle network errors. The library automatically retries, but will throw after max retries exhausted.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[12] - createBucket · createbucket-already-existserrorWhenBucket with same name already existsThrows
ApiError with HTTP 409 ConflictRequired handlingCaller SHOULD handle bucket already exists errors. If idempotent create is desired, catch 409 and retrieve existing bucket.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[13] - createBucket · createbucket-invalid-nameerrorWhenBucket name violates naming requirementsThrows
ApiError with HTTP 400 Bad RequestRequired handlingCaller MUST validate bucket names before creation. Names must be globally unique, lowercase, 3-63 characters, and follow DNS naming conventions.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[14] - createBucket · createbucket-permission-errorerrorWhenIAM permissions insufficient for bucket creationThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.buckets.create permission in the project.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[13] - deleteFiles · deletefiles-partial-failureerrorWhenSome files fail to delete while others succeedThrows
PartialFailureError containing array of failed operationsRequired handlingCaller MUST handle PartialFailureError separately from ApiError. Inspect error.errors array to determine which files failed and why. Consider retry logic for failed operations.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[15] - deleteFiles · deletefiles-permission-errorerrorWhenIAM permissions insufficient for batch deleteThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.delete permission on all matching files.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[15] - getSignedUrl · getsignedurl-invalid-credentialserrorWhenService account credentials are invalid or missingThrows
ApiError with authentication failureRequired handlingCaller MUST handle credential errors. Signed URLs require service account with private key. Verify GOOGLE_APPLICATION_CREDENTIALS is set correctly.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[16] - getSignedUrl · getsignedurl-file-not-founderrorWhenFile does not exist (for read operations)Throws
ApiError with HTTP 404 Not FoundRequired handlingCaller SHOULD handle file not found errors. For read URLs, file must exist. For write URLs, file will be created on upload.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[16] - copy · copy-source-not-founderrorWhenSource file does not exist in the bucketThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller MUST handle not found errors. Verify source file exists before copying, or catch 404 and handle gracefully. Common when copying files from user-uploaded content that may have been deleted concurrently.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - copy · copy-permission-errorerrorWhenInsufficient IAM permissions to read source or write to destinationThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors. Requires storage.objects.get on source and storage.objects.create on destination bucket. Cross-bucket copies also require the service account to have permissions on the destination project. This error is NOT automatically retried.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[17] - copy · copy-precondition-failedwarningWhenGeneration or metageneration precondition check failsThrows
ApiError with HTTP 412 Precondition FailedRequired handlingCaller MUST handle precondition failures when using ifGenerationMatch or ifMetagenerationMatch options. This error indicates the object was modified between the time the caller last read it and the copy attempt. Retry with updated preconditions or handle as a conflict.costlowin prodimmediate exceptionusers seelost datavisibilitysilentSources[17] - move · move-non-atomic-duplicate-riskerrorWhenCopy succeeds but delete of source fails, leaving duplicate filesThrows
ApiError from the delete phase — source file still exists alongside copied destinationRequired handlingCaller MUST handle move() errors by checking whether the destination was successfully created before treating the error as a full failure. If delete fails with 404 (already deleted by another process), treat as success. Consider using moveFileAtomic() for same-bucket moves that require atomicity. The file.move() non-atomicity is explicitly documented: "a composition of File#copy and File#delete... which could leave a duplicate file lingering."costhighin prodimmediate exceptionusers seelost datavisibilitysilentSources[19] - move · move-source-not-founderrorWhenSource file does not existThrows
ApiError with HTTP 404 Not Found (from copy phase)Required handlingCaller MUST handle not found errors. Verify source file exists before moving. 404 errors occur in the copy phase (source doesn't exist) or delete phase (source was deleted between copy and delete, which is safe to ignore).costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[19] - rename · rename-non-atomic-duplicate-riskerrorWhenUnderlying move() operation leaves duplicate files if delete failsThrows
ApiError — inherits from move() non-atomic behaviorRequired handlingCaller MUST handle rename() errors the same way as move() errors. If an error is thrown, the file may have been copied to the new name but the original not deleted, resulting in duplicates. Check destination existence before retrying.costmediumin prodimmediate exceptionusers seelost datavisibilitysilentSources[20] - rename · rename-not-founderrorWhenFile does not existThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller MUST handle not found errors. Verify file exists before renaming.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[20] - TransferManager.uploadManyFiles · transfer-upload-many-all-or-nothingerrorWhenAny single file upload fails — the entire batch fails with Promise.all rejectionThrows
ApiError from the first failing upload — other in-flight uploads are NOT cancelledRequired handlingCaller MUST handle errors as a batch failure. uploadManyFiles() uses Promise.all() internally, so the first file failure throws, but other concurrent uploads continue to their natural completion (they are NOT cancelled). Some files may have been uploaded successfully before the error is surfaced. To identify which files succeeded, check GCS for the uploaded objects after the error. For resilient batch uploads, use individual bucket.upload() calls with your own error tracking, or wrap each upload in a try-catch before using Promise.all.costmediumin prodimmediate exceptionusers seelost datavisibilitysilentSources[21] - TransferManager.uploadManyFiles · transfer-upload-many-permission-errorerrorWhenService account lacks write permissions on the bucketThrows
ApiError with HTTP 403 Forbidden from the first file that encounters the permission errorRequired handlingCaller MUST handle permission errors. Verify service account has storage.objects.create permission before starting a batch upload. Permission errors will typically affect ALL files in the batch.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[21] - TransferManager.downloadManyFiles · transfer-download-many-all-or-nothingerrorWhenAny single file download fails — the entire batch failsThrows
ApiError from the first failing downloadRequired handlingCaller MUST handle errors as a batch failure. downloadManyFiles() uses Promise.all() — the first file failure throws and surfaces as the batch error, but other concurrent downloads continue running. Some files may be written to disk while others are missing. Check local filesystem for which files were successfully downloaded before retrying.costmediumin prodimmediate exceptionusers seelost datavisibilitysilentSources[21] - TransferManager.downloadManyFiles · transfer-download-many-file-not-founderrorWhenOne or more requested files do not exist in the bucketThrows
ApiError with HTTP 404 Not Found from the first missing fileRequired handlingCaller MUST handle not found errors. Verify all files exist before starting a batch download, or use skipIfExists option to avoid overwriting local files. A single missing file will fail the entire batch.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[21] - TransferManager.downloadFileInChunks · transfer-download-chunks-crc32c-mismatcherrorWhenCRC32C validation enabled and assembled file does not match stored checksumThrows
RequestError with code 'CONTENT_DOWNLOAD_MISMATCH'Required handlingCaller MUST handle CONTENT_DOWNLOAD_MISMATCH errors when using validation: 'crc32c'. This error means data was corrupted in transit — some downloaded chunks did not assemble correctly. The local file is incomplete or corrupted. Delete the local file and retry the download. Use err.code === 'CONTENT_DOWNLOAD_MISMATCH' to detect this specific error type.costhighin prodimmediate exceptionusers seelost datavisibilitysilentSources[21] - TransferManager.downloadFileInChunks · transfer-download-chunks-file-not-founderrorWhenFile does not exist in the bucket (fails at metadata fetch stage)Throws
ApiError with HTTP 404 Not Found (from file.get() call)Required handlingCaller MUST handle not found errors. The download fails at the metadata retrieval stage (before any chunks are downloaded) if the file doesn't exist. No partial files are written to disk at this stage.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[21] - TransferManager.downloadFileInChunks · transfer-download-chunks-partial-chunk-failureerrorWhenOne or more chunk downloads fail mid-transfer after file is opened for writingThrows
ApiError from the first failed chunk downloadRequired handlingCaller MUST handle chunk failures. When a chunk fails, the local file handle is still closed (finally block), but the file on disk will be partially written with missing or corrupted byte ranges. Delete the partially written file before retrying. Do not rely on a partially downloaded file.costhighin prodimmediate exceptionusers seelost datavisibilitysilentSources[21] - TransferManager.uploadFileInChunks · transfer-upload-chunks-multipart-errorerrorWhenAny chunk upload or upload initiation failsThrows
MultiPartUploadError with uploadId and partsMap properties (NOT a standard ApiError)Required handlingCaller MUST catch MultiPartUploadError specifically — it is NOT a subclass of ApiError. The error contains two critical properties for resuming: - err.uploadId: the GCS multipart upload ID (to resume the upload later) - err.partsMap: Map of successfully uploaded part numbers to ETags Store these values to resume the upload. Pass them back as options.uploadId and options.partsMap to resume from the last successful chunk. If autoAbortFailure is true (default), the upload is automatically aborted on failure and these fields contain the aborted session — the upload cannot be resumed. Set autoAbortFailure: false to enable resumable failures.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[21] - TransferManager.uploadFileInChunks · transfer-upload-chunks-permission-errorerrorWhenService account lacks permission to initiate or complete multipart uploadThrows
MultiPartUploadError wrapping an underlying 403 Forbidden from GCS XML APIRequired handlingCaller MUST handle permission errors from uploadFileInChunks(). The underlying 403 is wrapped in MultiPartUploadError. Verify service account has storage.objects.create permission. The uploadId in the error will be empty/null if the failure occurred during upload initiation (before any parts were uploaded).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[21] - combine · combine-source-limit-exceedederrorWhenMore than 32 source objects passed in a single compose requestThrows
ApiError with HTTP 400 Bad Request from GCS — compose API rejects sources.length > 32Required handlingCaller MUST handle the 32-source cap. The GCS compose REST API limits a single request to 32 source components. For larger composes, caller must do a multi-level compose: combine 32 sources into intermediate objects, then combine the intermediates. Without try-catch, the rejection surfaces as an unhandled promise rejection and the partial workflow (e.g. chunked upload assembly) stalls with no remediation hint.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - combine · combine-source-not-founderrorWhenOne or more source files referenced in sources[] do not exist (HTTP 404)Throws
ApiError with HTTP 404 Not Found — naming the missing source object in the messageRequired handlingCaller MUST handle source-missing errors. Compose fails atomically — if any one source object is missing, no destination object is created. This is common when a parallel upload path (e.g. chunked uploadFileInChunks or TransferManager) had a partial failure and the missing chunk was retried under a different name. Distinguish 404 from 403 to avoid silently retrying a request that will always fail.costmediumin prodimmediate exceptionusers seelost datavisibilityvisibleSources[23] - combine · combine-precondition-failedwarningWhenifGenerationMatch on the destination does not match — concurrent compose conflictThrows
ApiError with HTTP 412 Precondition FailedRequired handlingCaller MUST handle 412 precondition failures. When ifGenerationMatch is set on the destination (or via instancePreconditionOpts), a concurrent writer may have updated the destination object since the caller read its generation. Compose becomes a no-op and the caller must re-read destination state and retry — or treat the conflict as a write-loss event. Without explicit handling, a parallel assembly job will silently produce stale output or duplicate the work.costmediumin prodimmediate exceptionusers seelost datavisibilitysilent - moveFileAtomic · move-file-atomic-non-hns-bucketerrorWhenCalled on a bucket without hierarchical namespace enabledThrows
ApiError with HTTP 400 Bad Request — moveTo endpoint rejects non-HNS bucketsRequired handlingCaller MUST handle non-HNS errors with a fallback path. moveFileAtomic only works on HNS buckets — most existing GCS buckets are flat. Catch the 400 and either fall back to file.move() (and accept the non-atomic semantics), or surface a configuration error to operators so they enable HNS at bucket-creation time (HNS cannot be enabled retroactively). Without try-catch, callers silently assume atomicity they do not have.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - moveFileAtomic · move-file-atomic-precondition-failederrorWhenifGenerationMatch precondition does not match the destination's current generationThrows
ApiError with HTTP 412 Precondition FailedRequired handlingCaller MUST handle 412 precondition failures. When preconditionOpts.ifGenerationMatch is set, a concurrent writer may have created or updated the destination since the caller's last read. moveFileAtomic does not overwrite — it fails. Without explicit 412 handling, retrying with the same precondition will loop indefinitely; the caller must re-read the destination, decide whether to overwrite, and resubmit.costmediumin prodimmediate exceptionusers seelost datavisibilitysilentSources[25] - moveFileAtomic · move-file-atomic-source-not-founderrorWhenSource file does not exist or was deleted before the move request landedThrows
ApiError with HTTP 404 Not FoundRequired handlingCaller MUST handle source-not-found errors. Unlike file.move() (where a 404 in the delete phase is benign), a 404 from moveFileAtomic always means the source never moved — the destination was not created. Treat as a hard failure and investigate whether another worker raced the move or the source was cleaned up prematurely.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[25] - lock · lock-precondition-failederrorWhenifMetagenerationMatch does not match — bucket metadata changed since caller read itThrows
ApiError with HTTP 412 Precondition FailedRequired handlingCaller MUST handle 412 precondition failures. The lock request includes the metageneration the caller observed; if any other writer mutated bucket metadata between the read and the lock call, the lock is rejected. Without try-catch, the operator sees a generic promise rejection and may retry the lock against stale state — locking the WRONG retention period permanently. Re-fetch getMetadata(), re-confirm the retention period is the intended value, and only then resubmit.costcriticalin prodimmediate exceptionusers seelost datavisibilityvisible - lock · lock-no-retention-policyerrorWhenBucket has no retention policy to lock — nothing to lockThrows
ApiError with HTTP 400 Bad Request — lockRetentionPolicy on bucket without policyRequired handlingCaller MUST handle the no-policy case. lock() only works when a retention policy is already set via setRetentionPeriod(). If called on a bucket with no policy, the API returns 400. Without try-catch, the deployment scripts that enforce compliance posture silently believe they locked the bucket — but the bucket has no retention enforcement at all. This is a compliance-audit time bomb. Verify getMetadata().retentionPolicy exists before calling lock().costcriticalin prodimmediate exceptionusers seesecurity breachvisibilitysilentSources[26] - lock · lock-permission-errorerrorWhenService account lacks storage.buckets.update or the role required to lock retentionThrows
ApiError with HTTP 403 ForbiddenRequired handlingCaller MUST handle permission errors on lock(). Locking a retention policy requires elevated permissions (typically Storage Admin or a custom role with storage.buckets.update). A silently-swallowed 403 means compliance automation believes locking succeeded but the policy remains mutable. Verify the service account role at deployment time and surface 403s as a hard failure to the compliance owner.costhighin prodimmediate exceptionusers seesecurity breachvisibilitysilentSources[27]
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
- [2]googleapis.dev/nodejs/storage/latestBucket
- [4]googleapis.dev/nodejs/storage/latestFile
- [7]googleapis.dev/nodejs/storage/latestFile
- [8]googleapis.dev/nodejs/storage/latestBucket
- [9]googleapis.dev/nodejs/storage/latestFile
- [10]googleapis.dev/nodejs/storage/latestFile
- [11]googleapis.dev/nodejs/storage/latestFile
- [12]googleapis.dev/nodejs/storage/latestBucket
- [13]googleapis.dev/nodejs/storage/latestStorage
- [14]cloud.google.com/storage/docs/naming-bucketsNaming Buckets
- [15]googleapis.dev/nodejs/storage/latestBucket
- [16]googleapis.dev/nodejs/storage/latestFile
- [17]googleapis.dev/nodejs/storage/latestFile
- [18]cloud.google.com/storage/docs/json_apiRewrite
- [19]googleapis.dev/nodejs/storage/latestFile
- [20]googleapis.dev/nodejs/storage/latestFile
- [21]googleapis.dev/nodejs/storage/latestTransferManager
- [22]cloud.google.com/storage/docs/json_apiCompose
- [23]googleapis.dev/nodejs/storage/latestBucket
- [24]cloud.google.com/storage/docs/json_apiMove
- [25]googleapis.dev/nodejs/storage/latestFile
- [26]cloud.google.com/storage/docs/json_apiLockRetentionPolicy
- [27]googleapis.dev/nodejs/storage/latestBucket
- [1]github.com/googleapis/nodejs-storage/issuesgoogleapis/nodejs-storage issue #833
- [3]github.com/googleapis/nodejs-storage/issuesgoogleapis/nodejs-storage issue #813
- [5]github.com/googleapis/nodejs-storage/issuesgoogleapis/nodejs-storage issue #2482
- [6]github.com/googleapis/nodejs-storage/issuesgoogleapis/nodejs-storage issue #709
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
Sources: @google-cloud/storage
Official Documentation
API Reference
-
Google Cloud Storage Node.js Client API: googleapis.dev/nodejs/storage/latest/
- Complete class and method documentation
- Error types: ApiError, PartialFailureError
- All async methods throw errors on failures
-
Storage Class Reference: googleapis.dev/nodejs/storage/latest/Storage.html
- createBucket(), getBuckets(), createHmacKey() methods
- All throw ApiError on network/auth failures
-
Bucket Class Reference: googleapis.dev/nodejs/storage/latest/Bucket.html
- upload(), delete(), deleteFiles(), getFiles() methods
- Batch operations throw PartialFailureError
-
File Class Reference: googleapis.dev/nodejs/storage/latest/File.html
- download(), save(), delete(), copy() methods
- Streams (createReadStream/createWriteStream) emit error events
- 404 errors when file doesn't exist
-
TransferManager Class Reference: googleapis.dev/nodejs/storage/latest/TransferManager.html
- downloadManyFiles(), uploadManyFiles() for batch operations
- Throws PartialFailureError for partial failures
Error Handling & Retry Strategy
-
Retry Strategy Guide: docs.cloud.google.com/storage/docs/retry-strategy
- Automatic retry for HTTP 408, 429, 500, 502, 503, 504
- Exponential backoff configuration
- Idempotent vs non-idempotent operations
- Default: 3 retries, 600s timeout, 2x multiplier
-
Configure Retries Sample: docs.cloud.google.com/storage/docs/samples/storage-configure-retries
- Full Node.js example with retry configuration
- Parameters: autoRetry, retryDelayMultiplier, totalTimeout, maxRetryDelay, maxRetries
- IdempotencyStrategy options
Best Practices
- Cloud Storage Best Practices: docs.cloud.google.com/storage/docs/best-practices
- Error handling recommendations
- Retry strategies
- Performance optimization
HTTP Status Codes
-
HTTP Status and Error Codes: cloud.google.com/storage/docs/json_api/v1/status-codes
- Complete list of HTTP status codes
- 4xx client errors (401, 403, 404, 408, 429)
- 5xx server errors (500, 502, 503, 504)
- Error response format
-
API Error Class: cloud.google.com/nodejs/docs/reference/storage/7.2.0/storage/apierror
- ApiError constructor and properties
- Error message structure
npm Package
- @google-cloud/storage on npm: npmjs.com/package/@google-cloud/storage
- Current version: 7.x (latest)
- Stable since v5.0.0
- Weekly downloads: 2M+
GitHub Repository & Issues
-
GitHub Repository: github.com/googleapis/nodejs-storage
- Official Google Cloud Node.js client
- Active maintenance and support
-
Error Message Issues: github.com/googleapis/nodejs-storage/issues/170
- Discussion of error messages in Node.js console
- ApiError: "Error during request" patterns
-
CONTENT_DOWNLOAD_MISMATCH Error: github.com/googleapis/nodejs-storage/issues/709
- Download corruption detection
- Retry recommendation when mismatch occurs
-
Upload 404 Errors: github.com/googleapis/nodejs-storage/issues/813
- bucket.upload() 404 error patterns
- Debugging permission and bucket existence
-
Socket Errors (ECONNRESET): github.com/googleapis/nodejs-storage/issues/2482
- Socket errors should be thrown directly
- Methods that perform fetch operations throw connection errors
-
High Load Errors (408): github.com/googleapis/nodejs-storage/issues/833
- 408 Request Timeout under high load
- Automatic retry mechanism
Error Handling Patterns
Error Types
-
ApiError - Primary error class for all API failures
- Network errors (ECONNRESET, ETIMEDOUT)
- HTTP errors (404, 408, 429, 5xx)
- Authentication errors (401)
- Permission errors (403)
-
PartialFailureError - Batch operation partial failures
- deleteFiles() when some deletions fail
- downloadManyFiles() / uploadManyFiles()
- Contains details of which operations failed
-
Network Errors
- ECONNRESET: Connection reset by peer
- ETIMEDOUT: Operation timeout
- EAI_AGAIN: DNS lookup errors
-
Special Errors
- CONTENT_DOWNLOAD_MISMATCH: Download corruption detected
- Stream 'error' events from createReadStream/createWriteStream
Automatically Retried
The client library automatically retries these conditions:
- HTTP 408, 429, 500, 502, 503, 504
- Network connection errors
- DNS lookup failures
- Uses exponential backoff (default: 3 retries, 2x multiplier, max 64s delay)
Require Manual Handling
These errors are NOT automatically retried:
- 401 Unauthorized (invalid credentials)
- 403 Forbidden (insufficient permissions)
- 404 Not Found (resource doesn't exist)
- Invalid configuration errors
Contract Rationale
All async operations in @google-cloud/storage can fail due to:
- Network issues: Connection timeouts, resets, DNS failures
- Authentication: Invalid or expired credentials
- Authorization: Insufficient IAM permissions
- Resource issues: Bucket/file doesn't exist (404)
- Rate limiting: Too many requests (429)
- Server errors: Google Cloud internal errors (5xx)
The library throws exceptions for all failures. Unhandled exceptions will crash Node.js applications.
Stream operations (createReadStream, createWriteStream) emit 'error' events instead of throwing, requiring event handlers to prevent process crashes.
Minimum Safe Version
>=5.0.0
- Stable API with comprehensive error handling
- Full retry mechanism with exponential backoff
- ApiError and PartialFailureError error classes
- Configurable retry options
Research Date
2026-02-27