Documentation Index

Fetch the complete documentation index at: https://cloudinary.com/documentation/llms.txt

Use this file to discover all available pages before exploring further.

Image & Video APIs

How to diagnose 40x and X-Cld-Error messages when delivering assets

Last updated: Sep-09-2026

When a delivery URL fails, Cloudinary returns an HTTP 40X status and often adds detail in the X-Cld-Error response header. This article explains how to read those signals, why some errors keep appearing after you fix the underlying issue (CDN caching), and what each common X-Cld-Error message means—with fixes—for 400, 401, and 404 responses.

For a walkthrough, see the Diagnosing error codes video tutorial. For complex cases, contact Cloudinary support.

How to diagnose delivery errors

X-Cld-Error header

When Cloudinary can't deliver an asset as requested (or returns a substitute such as the default image placeholder), the response may include an X-Cld-Error HTTP header with a more specific reason.

You can inspect X-Cld-Error headers with your browser's developer tools. For step-by-step instructions on how to do this in different browsers, see How to inspect errors manually.

See also:

X-Cld-Error inspector tool

Use the tool below to inspect the X-Cld-Error header for a Cloudinary image URL. Paste the transformation URL and choose Inspect Headers.

Note
If the tool fails to retrieve headers, you can inspect them manually using your browser's Developer Tools Network tab.

HTTP status codes

The HTTP status (400, 401, 404, etc.) summarizes the outcome; X-Cld-Error (when present) narrows down the cause. The sections below are grouped by status code, with subsections for typical situations and for specific X-Cld-Error strings.

Cached 40X responses at the CDN

Cloudinary caches 40X error responses at the CDN per exact URL, using exponential backoff:

  • The first cached 40X for a given URL lasts 1 minute.
  • After that entry expires, if the same URL is requested and still fails, the next cached 40X lasts twice as long as the previous period (2 minutes, 4 minutes, 8 minutes, and so on), up to a maximum of 24 hours per cache segment.
  • After that maximum, repeated failures can keep the error cached in 24-hour increments.

You see this most often as 404 on a transformation URL when the original asset wasn't in your cloud when you first tried to deliver the URL, or when the public_id specified in the URL doesn't match what you later uploaded.

Upload and delivery often run in different places—for example, one service uploads while another app or job only builds or loads transformation URLs. Those paths don't always finish in the same order, so a transformation URL can be requested before the asset exists.

In this case, the CDN may respond with a 40X (often 404) and cache that error response. Due to this caching, the URL can continue failing for a while even after the upload completes.

If you get a 40X (such as 404) and you've validated that the asset is in your cloud, a cached error for that exact URL is a likely explanation, especially if other transformation URLs for the same asset work.

Tip
Test for a cached error. Append a no-impact transformation such as \a_0\ to the failing URL. If that variant works while the original URL still fails, you are probably seeing a cached error response.

Reduce or recover from cached errors

Prevent the issue: Upload the original (or apply the final public_id) before any code requests transformed URLs for that asset, so the first CDN hit isn't an error.

Work around an error that's already cached:

  • Add the asset's version to the URL after upload so the URL string changes and isn't the cached failure.
  • Use different transformation parameters or change the order of transformations so the URL isn't identical to the cached one.
  • Use a default image placeholder (default_image / d in URLs) so delivery doesn't return a bare 404 while the asset is missing or while a cached error is still in effect.
  • Invalidate the broken cached version so the new version can be immediately delivered instead
    • When renaming a public ID programmatically to one that is currently returning a cached 404, include the invalidate parameter in the rename request
    • If the asset you want to deliver already exists with the same public ID as one currently returning a cached 404 (for example, if you uploaded a new version of the asset without applying invalidate during the upload), use Explicit with the invalidate parameter set to true.

Tip
You can run an Explicit or Rename with invalidation quickly using the Asset Management MCP server, the Cloudinary Postman collection, or the CLI.

In general, when replacing an image with the same public_id: Upload with overwrite: true and invalidate: true so CDN copies of the old file and its derivatives are cleared. For example:

Tip
Instead of invalidation, you can rely on a new asset version in the URL so clients request a URL that bypasses the old cached object.

400 Bad Request

400 usually means the URL or transformation is invalid, malformed, or not allowed in the way it was requested—for example unknown transformation parameters or values (such as invalid tokens or w_0), or syntactically valid options that conflict (such as g_auto with a crop mode that doesn't support it).

Wrong URL structure also yields 400—for example if cloud_name appears after resource_type / type in the wrong place, or if transformation segments are embedded inside the public_id. See Transformation URL structure.

The subsections below describe frequent X-Cld-Error patterns for 400 and how to fix them.

Unknown or invalid referenced image <public_id> of type upload

  • Cause: Cloudinary can't find the referenced image (e.g. in overlays or other references).
  • What to do:
    • Confirm the public_id and that the resource still exists; fix any broken references in the request.
    • If the public_id contains slashes (e.g. animals/dog), use colons in overlay references (e.g. animals:dog).

Error in loading - <remote source URL>

  • Cause: With fetch delivery, Cloudinary couldn't retrieve the remote file. X-Cld-Error is often Error in loading <URL> - <HTTP status from the remote>; Cloudinary returns 400 for that case. If the remote returns 404, Cloudinary more often returns 404 with Resource not found - <URL> instead. Causes include network issues, blocking, or the origin being down.
  • What to do: Verify the URL; confirm the origin is up and reachable from the public internet; rule out access or rate limits on the remote.

Invalid transformation

  • Cause: The transformation parameter or value is invalid, or the URL is malformed relative to supported syntax.
  • What to do: Align parameters and values with the transformation reference and fix URL structure.

Invalid transformation parameter - <prefix> (folder name read as a transformation)

This error is misleading, because the problem is usually the folder path, not a transformation. It reports only the characters before the underscore, so the folder name it objects to doesn't appear in the message.

  • Cause: A path element in the public ID starts with 1-3 characters followed by an underscore, such as my_path or abc_folder. Cloudinary reads URL components in that shape as a transformation component, because that's what transformation parameters look like (w_300, c_fill, t_preset), so it tries to parse the folder name as a parameter and rejects it. Delivering .../image/upload/my_path/sample.jpg returns 400 with Invalid transformation parameter - my.
  • What to do:
    • Separate the last transformation component from the path element with a version component, for example .../image/upload/t_transf1/t_transf2/v1/my_path/sample.jpg. A version on its own isn't enough: .../image/upload/v1/my_path/sample.jpg still fails, because there's no transformation component for the version to separate the path from.
    • When creating assets, avoid public ID path elements in this shape. See the notes under including a path in the public ID for the full recommendation.

Note
If the prefix happens to match a real parameter, the message is more confusing still: a path element such as a_x reports Invalid angle in transformation: x, because a is the angle parameter and Cloudinary validates the rest of the folder name as its value.

Tip
Path elements with 4 or more characters before the underscore aren't affected, so long_path or abcd_folder deliver normally.

Invalid encoding in transformation

  • Cause: A text overlay contains a character that needs four bytes in UTF-8, such as an emoji, and the URL passes those bytes through only one round of percent-encoding. Emojis sit above the Basic Multilingual Plane, so a character such as 👋 is %F0%9F%91%8B when encoded once, and Cloudinary rejects the transformation with Invalid encoding in transformation. Characters that need one to three bytes, such as é (%C3%A9) or ✓ (%E2%9C%93), are unaffected and work whether they're encoded once or twice.
  • What to do: Percent-encode the % signs themselves, so each byte reaches Cloudinary as %25 followed by its hex value: 👋 becomes %25F0%259F%2591%258B. That clears this error, but see the note below before using emojis in a text overlay.

Note
Emojis don't render in text overlays. Once the encoding is correct, emojis fail at the next step with Failed rendering text, because none of the supported fonts include emoji glyphs (and emoji-specific families such as Noto Color Emoji aren't supported). Double-encoding is therefore not a fix for emojis: it moves you from one error to another. To show an emoji, deliver it as an image overlay using an uploaded emoji graphic instead of a text overlay.

Non-emoji four-byte characters, such as the musical symbol 𝄞 (%25F0%259D%2584%259E), do render once double-encoded.

Tip
If a fix that should work keeps failing, check how the URL is generated before changing the encoding again. URLs built by a script, CMS, or ad-serving template, especially ones containing placeholders such as $name, often pass through an extra encoding step downstream, which changes how many rounds of encoding you need to apply yourself. Test the overlay in isolation first: open a minimal URL containing just the l_text layer directly in a browser, confirm it works, then add it back into the full URL.

Failed rendering text

  • Cause: The text overlay was decoded successfully, but Cloudinary couldn't render it with the requested font. The most common cause is a character with no glyph in that font, such as an emoji (see Invalid encoding in transformation above).
  • What to do: Check that every character in the overlay exists in the chosen font, using the supported fonts list. For emojis, use an image overlay instead. Note this is a different problem from Unsupported font family, which means the font name itself isn't recognized.

Auto gravity can only be used with crop, fill, thumb, lfill

  • Cause: g_auto is used with a resize mode that isn't a supported cropping mode (e.g. scale or fit).
  • What to do: Use g_auto only with compatible modes (crop, fill, lfill, fill_pad, thumb, etc.), or remove g_auto if you need an incompatible mode.

public_id is too long

  • Cause: For fetch delivery, the remote URL becomes the public_id. public_id length is limited (commonly 255 characters unless Cloudinary extends it for your account). Invalid transformation segments can be parsed as part of the public_id and trigger the same message.
  • What to do: Upload from the remote URL via the API, use upload mapping, or ask support about a higher limit.

Maximum image size is <n> Megapixels. Requested <n> Megapixels

  • Cause: The source image exceeds the megapixel limit for transformation processing on your plan. The limit applies to the image being processed, not to the delivered output, so requesting a small output size doesn't avoid it on its own.
  • What to do: Make a resize the first action in the transformation chain, so later actions run on the smaller image. If the original is consistently oversized, resize it on upload with an incoming transformation, or contact support about a higher limit.

File size too large. Got <n>. Maximum is <n>

  • Cause: The file exceeds the size limit for transformation processing on your plan. The limit applies to the file being processed, not to the delivered output.
  • What to do: Deliver a smaller original, or reduce the file before transforming it, for example by resizing it on upload with an incoming transformation. Contact support if you need the limit raised. For videos, see Video is too large to process synchronously below.

Rate Limit Exceeded. Limit of <n> <add-on> operations reached

  • Cause: You've used up the allowance for an add-on, such as an AI-based effect, for the current period. The message names the add-on and the date to try again. Add-on quotas follow your account's billing cycle rather than the rolling 30-day window used for transformations and bandwidth, so the allowance resets on your renewal date, not on a rolling basis. If you subscribe partway through a billing period, that period's quota is prorated.
  • What to do: Wait for the reset, or upgrade the add-on allocation in your Console. Each distinct transformation URL counts as one operation against the allowance, so check whether the same result is being requested under URLs that differ only slightly, for example through varying parameter order or unnecessary parameters. Keeping the URL stable means the derived asset is reused instead of generating a new operation.

Video is too large to process synchronously, please use an eager transformation with eager_async=true to resolve

  • Cause: On-the-fly (or non-async eager) video transforms exceed size limits (40MB on Free, 300MB on paid plans)—limits apply to transformation processing, not raw upload size.
  • What to do: Run transforms eagerly and set eager_async=true (upload, upload presets, Explicit, or fetch). Use eager_notification_url if you need a callback when processing finishes.

401 Unauthorized

401 means delivery was blocked by an access rule: Strict transformations without an allowed/signed derived, restricted features in the product environment (Security), private or authenticated assets without a valid signed URL or token, or similar controls.

ACL deny

  • Cause: Cloudinary returns 401 with ACL deny in X-Cld-Error when ACL rules, fetch allowlists, or related policies block the request. Other denials (e.g. token-based access or PDF / archive restrictions on free plans) can produce similar 401 responses; the exact X-Cld-Error text may differ.
  • What to do:
    • Review ACL dimensions you configured (country, IP, path, content-type, referrer, user-agent)
    • For token-based or cookie-based access, work through Troubleshooting a rejected token, which lists the mistakes that produce this error, including a token whose acl parameter, expiry, IP, or signing key is wrong
    • For free-plan PDF/archives, see the Media delivery guide; contact support if needed

<type> of type <media type> are restricted in this account

  • Cause: Delivery of that media type is restricted in your product environment, one of the restricted features that produce a 401. For example, Resources of type list are restricted in this account for the list delivery type, or Images of type fetch are restricted in this account for fetch delivery.
  • What to do: Open the Security page in your Console Settings and clear the relevant item under Restricted media types. For the list delivery type, clear Resource list under Restricted image types, as described in Delivering asset lists. You may prefer to clear these only temporarily, as needed. Alternatively, bypass any delivery type restriction with a signed URL.

Note
Fetch delivery is also restricted automatically if it isn't used within seven days of account creation, to prevent abuse. If fetch used to work and then stopped, check this setting first.

<cloud_name> cannot be accessed via this endpoint

  • Cause: The cloud name in the URL doesn't match the endpoint being used, for example a mismatched or misspelled cloud name, or a URL built for a different product environment. A disabled product environment produces a similar 401, with cloud_name <cloud_name> is disabled.
  • What to do: Confirm the cloud_name in the URL matches the product environment you intend to deliver from, and check the URL structure.

404 Not Found

404 means the requested resource wasn't found, unless you use a default / placeholder image transformation—in which case the response may still succeed with a substitute while X-Cld-Error can describe the underlying miss.

If 404 persists for a URL that should work after a recent upload or rename, see Cached 40X responses at the CDN above.

Resource not found - <public_id>

  • Cause: No resource matches the public_id (typo, deletion, or wrong path).
  • What to do:
    • Verify public_id and that the file still exists.
    • Confirm resource_type and delivery_type in the URL (image/upload, image/private, video/upload, etc.).
    • Look through your transformation parameters. If there's one that's missing an underscore, Cloudinary might try to resolve it as part of the public ID path. For example, cartoonify/my_image, when you intended e_cartoonify/my_image.

Resource not found (public ID isn't specified in the error message)

  • Cause: The real reason is hidden for security. For example, the URL may need a signature (private/authenticated assets, or add-ons that require signed URLs).
  • What to do: Check whether the asset or flow requires signed URLs. On paid plans, the Error report may show the underlying message; otherwise support can confirm or help adjust settings.

Resource not found - <URL> (fetch)

When fetch is used and the remote returns 404, X-Cld-Error often includes Resource not found - <URL> with HTTP 404 (contrast with 400 “Error in loading” for other remote HTTP failures, described under 400 above).

Slashes and colons in folder paths

A common cause of Resource not found is using the wrong separator for a folder path. The separator depends on where the public ID appears in the URL:

Where the public ID appears Separator Example
Base asset being delivered Forward slash (/) .../image/upload/animals/dog.jpg
Referenced asset in a transformation parameter, such as an overlay or underlay Colon (:) .../image/upload/l_animals:dog/...
  • Cause: Using a colon in a base public ID, or a slash in an l_ or u_ reference. Either way, Cloudinary looks for an asset that doesn't exist under that name.
  • What to do: Check which position the public ID is in, then apply the matching separator. If your product environment uses fixed folder mode, the folder path is part of the public ID, so include it. In dynamic folder mode, the asset's public ID is independent of its folder, so check the public ID value itself rather than assuming it mirrors the folder structure.

423 Locked

423 means the asset exists but the requested derived version is still being generated. It isn't a failure: the asset becomes available once processing finishes, and the same URL then succeeds unchanged. Cloudinary returns 423 for transformations that are processed asynchronously, such as adaptive bitrate streaming, background removal, video previews, long videos, and content-aware video cropping.

Resource pending / <transformation> is pending

  • Cause: The requested derived version is still being processed. The first request for such a derivation triggers the work, so it's the first request that receives 423. For example, Video tracking-crop is pending appears while automatic content-aware video cropping (g_auto) analyzes the video, which can take seconds or minutes depending on its length.
  • What to do:
    • Retry the URL after processing completes, rather than treating it as a missing asset. Subsequent requests to the same URL are served from cache.
    • To avoid the wait on the first request, generate the derived version ahead of time with an eager transformation, using explicit for assets you've already uploaded, and set eager_async=true for long-running derivations.
    • Use notifications (for example eager_notification_url) to find out when processing has finished, instead of polling the delivery URL.

Tip
If you're delivering these transformations in a web app, some SDK components handle the wait for you. For example, CldImage in Next.js polls a URL that returns 423 and refreshes the image once it's ready.

✔️ Feedback sent!

Rate this page:

one star two stars three stars four stars five stars