cloudinary
semver
>=1.0.0 <3.0.0postconditions17functions14last verified2026-04-15coverage score82%Postconditions — what we check
- upload · upload-missing-error-handlingerrorWhennetwork error, validation error, authentication failure, or quota exceeded during uploadThrows
Plain object { message: string, http_code: number } — NOT a standard Error instance. HTTP 401: Authorization required (invalid/missing api_key, api_secret, or cloud_name). HTTP 403: Not allowed (unsigned upload attempt with restricted params). HTTP 400: Bad request (invalid file type, transformation params, or public_id format). HTTP 420: Rate limited (upload quota exceeded). HTTP 500: Internal server error. Node.js Error object: network-level failure (ECONNREFUSED, ETIMEDOUT, DNS failure).Required handlingMUST wrap cloudinary.v2.uploader.upload() in try-catch (for async/await) OR check error parameter in callback: (error, result) => { if (error) ... } IMPORTANT: error is a plain object {message, http_code}, not Error instance. Check error.http_code to distinguish auth (401), permission (403), rate-limit (420).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - upload_large · upload-large-missing-error-handlingerrorWhennetwork interruption, chunk upload failure, authentication failure, or file size exceededThrows
Plain object { message: string, http_code: number } on chunk failure. HTTP 400: File exceeds account upload limit (>100MB without plan support, or >100GB). HTTP 401: Authorization required (invalid credentials). HTTP 500: Internal server error during chunk assembly. Node.js Error object: network failure between chunks (ETIMEDOUT mid-upload). TimeoutError object ({ name: 'TimeoutError' }): request timeout during chunk POST.Required handlingMUST wrap cloudinary.v2.uploader.upload_large() in try-catch OR check error parameter in callback. Files >100MB require this method. Partial uploads are NOT automatically cleaned up on failure.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - upload_stream · upload-stream-missing-error-handlingerrorWhenstream read error, network interruption, memory issue, or authentication failureThrows
Error delivered via callback parameter, NOT as a rejected Promise. The callback is the ONLY way to receive errors from upload_stream(). Error structure: { message: string, http_code: number } (plain object, not Error instance). HTTP 401: Authorization required. HTTP 400: Invalid transformation parameters or file format rejected. Node.js Error: stream read failure or EPIPE on stream pipe.Required handlingMUST provide callback with error parameter: cloudinary.v2.uploader.upload_stream((error, result) => { if (error) ... }) Stream uploads REQUIRE callback-based error handling — there is no Promise to catch. Piping to the returned stream without a callback will silently swallow errors.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - destroy · destroy-missing-error-handlingerrorWhenauthentication failure, network error, permission denied, or unexpected server errorThrows
Plain object { message: string, http_code: number } for API errors. HTTP 401: Authorization required (invalid credentials). HTTP 403: Not allowed (insufficient permissions for this resource type or delivery type). HTTP 500: Internal server error. Node.js Error: network-level failure (ECONNREFUSED, ETIMEDOUT). IMPORTANT: Missing asset does NOT throw — resolves with { result: 'not found' }. Callers checking result.result === 'ok' will miss this silent no-op.Required handlingMUST wrap cloudinary.v2.uploader.destroy() in try-catch for auth/network errors. ALSO check result.result === 'ok' to detect missing assets (not thrown as error). Example: if (result.result !== 'ok') { log warning about missing asset }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - rename · rename-missing-error-handlingerrorWhensource asset not found (HTTP 404), target public_id already exists with overwrite:false (HTTP 409), authentication failure (HTTP 401), or permission denied (HTTP 403)Throws
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 404: Source asset not found (from_public_id does not exist). HTTP 409: Target public_id already exists and overwrite option is false (default). HTTP 401: Authorization required (invalid api_key/api_secret). HTTP 403: Not allowed (permission denied for this resource type). HTTP 400: Bad request (invalid public_id format).Required handlingMUST wrap cloudinary.v2.uploader.rename() in try-catch. Check error.http_code: 404 means source missing, 409 means target conflict. Pass overwrite: true explicitly if overwrite behavior is intended.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - rename · rename-silent-conflictwarningWhenrename target public_id already exists and overwrite option is not set to true (HTTP 409)Throws
Plain object { message: string, http_code: 409 } — rejected with conflict message.Required handlingCheck error.http_code === 409 to distinguish "target already exists" from other failures. Either use overwrite:true or handle the conflict explicitly.costlowin prodsilent failureusers seedegraded performancevisibilityvisibleSources[2] - explicit · explicit-missing-error-handlingerrorWhenasset not found (HTTP 404), invalid transformation parameters (HTTP 400), authentication failure (HTTP 401), or rate limit exceeded (HTTP 420)Throws
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 404: Asset not found (public_id does not exist yet or was deleted). HTTP 400: Invalid transformation parameters (bad crop mode, unsupported format). HTTP 401: Authorization required (invalid credentials). HTTP 420: Rate limited (too many transformation requests in short window). HTTP 500: Internal error (transformation pipeline failure for complex operations).Required handlingMUST wrap cloudinary.v2.uploader.explicit() in try-catch. Check error.http_code: 404 means asset not yet available (consider retry with backoff), 400 means transformation params are wrong (check transformation options).costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - add_tag · add-tag-missing-error-handlingerrorWhenauthentication failure (HTTP 401), permission denied (HTTP 403), invalid tag format (HTTP 400), or network failure — add_tag() silently returns empty list for non-existent public_idsThrows
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 401: Authorization required. HTTP 403: Not allowed (permission denied). HTTP 400: Bad request (invalid tag format, too many public_ids). Node.js Error: network failure. SILENT: Non-existent public_ids do NOT throw — silently returns empty list.Required handlingMUST wrap cloudinary.v2.uploader.add_tag() in try-catch for auth/network errors. Check response.public_ids array to verify tags were actually applied.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - remove_tag · remove-tag-missing-error-handlingerrorWhenauthentication failure (HTTP 401), permission denied (HTTP 403), invalid tag or public_id format (HTTP 400), or network failure during tag removal operationThrows
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 401: Authorization required. HTTP 403: Not allowed. HTTP 400: Invalid tag or public_id format.Required handlingMUST wrap cloudinary.v2.uploader.remove_tag() in try-catch. For access-control use cases, verify the operation succeeded via response.public_ids.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - api.delete_resources · delete-resources-missing-error-handlingerrorWhenauthentication failure (HTTP 401), permission denied (HTTP 403), Admin API rate limit exceeded (HTTP 420), or network failure during bulk asset deletionThrows
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 401: Authorization required (invalid api_key/api_secret). HTTP 403: Not allowed (insufficient plan or resource-level permission). HTTP 420: Rate limited (Admin API hourly quota exceeded). HTTP 500: Internal server error. Node.js Error: network failure.Required handlingMUST wrap cloudinary.v2.api.delete_resources() in try-catch. Check error.http_code === 420 for rate limit and implement exponential backoff. Monitor X-FeatureRateLimit-Remaining header for proactive throttling. Check response.not_found[] array to verify which assets were actually deleted.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - api.resource · api-resource-missing-error-handlingerrorWhenasset not found (HTTP 404), authentication failure (HTTP 401), permission denied (HTTP 403), or Admin API rate limit exceeded (HTTP 420)Throws
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 404: Asset not found (public_id does not exist). HTTP 401: Authorization required. HTTP 403: Not allowed (insufficient permissions for this resource type). HTTP 420: Rate limited (Admin API quota exceeded).Required handlingMUST wrap cloudinary.v2.api.resource() in try-catch. Check error.http_code === 404 to handle missing assets gracefully (return null). Check error.http_code === 420 to implement backoff for high-volume metadata pipelines.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - update_metadata · update-metadata-missing-error-handlingerrorWhenauthentication failure (HTTP 401), invalid metadata field ID (HTTP 400), permission denied (HTTP 403), or network failureThrows
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 400: Bad request (invalid metadata field external_id, value type mismatch, or pipe-encoded metadata string is malformed). HTTP 401: Authorization required (invalid api_key/api_secret). HTTP 403: Not allowed (insufficient permissions for metadata operations). Node.js Error: network failure (ECONNREFUSED, ETIMEDOUT).Required handlingMUST wrap cloudinary.v2.uploader.update_metadata() in try-catch. Check error.http_code === 400 to detect field ID mismatches (field was renamed/deleted). Note: partial success is NOT reported — if any field is invalid, the entire batch rejects. Validate metadata field external_ids against your Cloudinary dashboard before batch updates.costmediumin prodimmediate exceptionusers seelost datavisibilitysilentSources[2] - update_metadata · update-metadata-silent-partial-failurewarningWhennon-existent public_ids silently succeed — update_metadata does NOT throw 404 for missing assets but silently omits them from the resultThrows
Resolves (does NOT reject) when assets don't exist. Response: { public_ids: string[] } — only lists public_ids that were updated. Missing assets are silently omitted from response.public_ids.Required handlingAfter awaiting update_metadata(), compare response.public_ids against your input public_ids array. If any are missing, log a warning — those assets don't exist and their metadata was not updated. Example: const missing = input.filter(id => !result.public_ids.includes(id))costlowin prodsilent failureusers seelost datavisibilitysilentSources[2] - api.update · api-update-missing-error-handlingerrorWhenasset not found (HTTP 404), invalid metadata field or value (HTTP 400), authentication failure (HTTP 401), permission denied (HTTP 403), or Admin API rate limit exceeded (HTTP 420)Throws
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 404: Asset not found (public_id does not exist or was deleted). HTTP 400: Invalid metadata field external_id, tag format, or context syntax. HTTP 401: Authorization required (Admin API key + secret required). HTTP 403: Not allowed (insufficient plan or resource-type permission). HTTP 409: Conflict (trying to set access_mode to its current value). HTTP 420: Rate limited (Admin API hourly quota exceeded). Node.js Error: network failure (ECONNREFUSED, ETIMEDOUT).Required handlingMUST wrap cloudinary.v2.api.update() in try-catch. Check error.http_code === 404 to handle deleted assets gracefully. Check error.http_code === 420 to implement exponential backoff. Monitor X-FeatureRateLimit-Remaining in response for proactive throttling. Note: unlike delete_resources, api.update() updates a single asset atomically.costmediumin prodimmediate exceptionusers seelost datavisibilitysilentSources[4] - api.delete_resources_by_tag · delete-resources-by-tag-missing-error-handlingerrorWhenauthentication failure (HTTP 401), permission denied (HTTP 403), Admin API rate limit exceeded (HTTP 420), or network failure during bulk tag-based deletionThrows
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 401: Authorization required (Admin API credentials required). HTTP 403: Not allowed (insufficient permissions for bulk delete). HTTP 420: Rate limited (Admin API quota exceeded — operation NOT applied). Node.js Error: network failure.Required handlingMUST wrap cloudinary.v2.api.delete_resources_by_tag() in try-catch. CRITICAL: Verify tag scope before calling — this deletes ALL assets with that tag. Use api.resources_by_tag() first to preview what will be deleted. Check error.http_code === 420 for rate limit and implement exponential backoff. Enable Cloudinary backup feature in account settings if data recovery is required. Consider using delete_resources() with explicit public_ids for safer targeted deletion.costhighin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - api.delete_resources_by_tag · delete-resources-by-tag-catastrophic-misuseerrorWhenbulk tag-based deletion applied without prior scope verification — resolves successfully but deletes more assets than intended due to shared or generic tag nameThrows
Resolves (does NOT reject) when the deletion succeeds — even if it deleted more assets than intended. Response: { deleted: {}, deleted_counts: {}, partial: boolean, rate_limit_... } No per-asset confirmation — only aggregate counts.Required handlingALWAYS call api.resources_by_tag(tag) first to preview the asset count and verify the tag scope before deletion. Use a dedicated deletion-scoped tag (e.g., "to-delete-YYYY-MM-DD") to avoid accidental scope bleed. Store the list of deleted public_ids from resources_by_tag() before calling delete_resources_by_tag() for audit logging.costcriticalin prodsilent failureusers seelost datavisibilitysilentSources[4] - search.execute · search-execute-missing-error-handlingerrorWheninvalid search expression (HTTP 400), missing Admin API credentials (HTTP 401), rate limit exceeded (HTTP 420), or network failureThrows
Plain object { message: string, http_code: number } — NOT a standard Error. HTTP 400: Bad request (invalid search expression syntax, malformed Lucene query). HTTP 401: Authorization required (Admin API credentials required, not just upload key). HTTP 420: Rate limited (Admin API quota, search counts against the same limit). HTTP 500: Internal error (query too broad, index timeout).Required handlingMUST wrap cloudinary.v2.search.expression(...).execute() in try-catch. Check error.http_code === 400 to detect expression syntax errors. Check error.http_code === 401 — search requires Admin API credentials (api_key + api_secret), not just cloud_name. Client-side usage will always return 401. Implement pagination with next_cursor for large result sets to avoid timeouts.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[5]
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
- [1]cloudinary.com/documentation/upload_imageshttps://cloudinary.com/documentation/upload_images
- [2]cloudinary.com/documentation/image_upload_api_referencehttps://cloudinary.com/documentation/image_upload_api_reference
- [3]support.cloudinary.com/hc/en-ushttps://support.cloudinary.com/hc/en-us/community/posts/360026620212-stream-upload-catching-errors-NODE-JS-
- [4]cloudinary.com/documentation/admin_apihttps://cloudinary.com/documentation/admin_api
- [5]cloudinary.com/documentation/search_apihttps://cloudinary.com/documentation/search_api
Need a different package?
Request a profile