If you would rather not keep this table in your own code, PostWharf, the tool we make, publishes to Instagram from one API call and writes the reason for a refusal on the post's delivery receipt as a sentence.
How to read an Instagram API error
The error object carries a message, a type, a code and usually an error_subcode. It can also carry error_user_title and error_user_msg, which are written for the person using your app, and an fbtrace_id to quote when you report a bug to Meta. The sample in Meta's Instagram reference adds is_transient, which is false in its oversized-image example.
Three habits make the object useful:
- Look up the subcode first. The code is only a family. Code 100 covers an unknown media type, a carousel with the wrong number of items and a post with too many tags, and the subcode is what tells them apart.
- Match on the numbers, never on the sentence. The user-facing title and message follow the locale of the request, so the same refusal can arrive in the account's language. A handler that searches the text for a word will miss it.
- Keep the
fbtrace_idwith your record of the attempt. Meta asks for it when you report a bug.
Meta lists every 2207 subcode in its reference under HTTP status 400, so the status line alone tells you nothing.
Instagram publishing error codes, by cause
The codes and messages come from Meta's Instagram Platform error-codes reference (updated 2 June 2026) and its Graph API error-handling guide, both read on 10 November 2026. Curly braces mark a value Instagram fills in. "Retry as is" means sending the same request again with nothing changed.
Sign-in and permission errors
| Code | Subcode | Message Instagram shows | What it means | Fix | Retry as is? |
|---|---|---|---|---|---|
| 190 (or 102) | 460, 463, 467 or none | Error validating access token | The access token has expired, been revoked or is otherwise invalid. Subcode 460 means the password changed, 463 that the token expired, 467 that it is invalid. | The account owner signs in again to issue a new token. | No |
| 10 | none | Application does not have permission for this action | The permission to publish was never granted, or has been removed. | Reconnect the account and grant the content publishing permission. | No |
| 10 | 2207081 | Application does not have permission for this action | A trial Reel was sent from an account with too few followers for trial Reels. This one is not in Meta's reference; it is from our own delivery logs. | Publish it as a normal Reel. | No |
| 200 to 299 | none | Varies with the permission | A specific permission is missing or was removed. | Same as code 10. | No |
| 24 | 2207006 | The media with {media-id} cannot be found | Possibly a missing permission or an expired token rather than lost media. | Check the token and its permissions, then create a new container. | No, new container |
| 25 | 2207050 | The Instagram account is restricted. | The professional account is inactive, checkpointed or restricted. | The owner signs in to the Instagram app and completes whatever it asks for. | No |
Limits and blocks
| Code | Subcode | Message Instagram shows | What it means | Fix | Retry as is? |
|---|---|---|---|---|---|
| 9 | 2207042 | You reached maximum number of posts that is allowed to be published by Content Publishing API. | The account has used its publishing allowance for the current 24 hours. | Wait for the window to move on. Meta's advice is to try again the following day. | No, wait |
| 4 | 2207051 | We restrict certain activity to protect our community. | Instagram suspects the publishing activity is spam. | Slow down, and tell Meta if the block is a mistake. | No |
| 4 or 17 | none | Varies | Too many calls from the app (4) or on behalf of one user (17). The throttle is temporary. | Wait, then look at how many requests you send. | Yes, after a wait |
Container and timing errors
| Code | Subcode | Message Instagram shows | What it means | Fix | Retry as is? |
|---|---|---|---|---|---|
| 9007 | 2207027 | The media is not ready for publishing, please wait for a moment | Publish was called before Instagram finished processing the media. | Read the container's status_code and publish once it says FINISHED. | Yes, same container |
| 24 | 2207008 | The media builder with creation id = {creation-id} does not exist or has been expired. | A temporary fault while publishing the container. | Try again once or twice over the next 30 seconds to 2 minutes. If it still fails, create a new container. | Yes, once or twice |
| -2 | 2207020 | The media you are trying to access has expired. | The container expired before it was published. | Create a new container and publish that one. | No, new container |
| -2 | 2207003 | It takes too long to download the media. | Instagram timed out while fetching your file. | Send it again. If it keeps happening, check how quickly your file host answers. | Yes |
| -1 | 2207001 | (no message given) | An error on Instagram's side. | Send it again. If it came back from the publish step, read the container's status first. | Yes |
| -1 | 2207032 | Create media fail, please try to re-create media | The container could not be created. | Create it again. | Yes |
| -1 | 2207053 | unknown upload error | An unexplained failure during upload, on video only. | Create a new container and upload again. | No, new container |
Media and caption errors
| Code | Subcode | Message Instagram shows | What it means | Fix | Retry as is? |
|---|---|---|---|---|---|
| 36000 | 2207004 | The image is too large to download. It should be less than {size}. | The image is over 8 MiB. | Export a smaller file. | No |
| 36001 | 2207005 | The image format {format} is not supported. | The file is in a format Instagram will not take. JPEG is the only image format its publishing API supports. | Convert the image to JPEG. | No |
| 36003 | 2207009 | The submitted image with aspect ratio {ratio} cannot be published. | The image falls outside the 4:5 to 1.91:1 range. | Crop it to fit. | No |
| 36004 | 2207010 | The submitted image's caption was {length} characters long. | The caption is over 2,200 characters. Meta's entry also gives ceilings of 30 hashtags and 20 @ tags. | Shorten the caption. | No |
| 352 | 2207026 | The video format is not supported. | The video is not an MOV or MP4 file. | Export it again as MOV or MP4. | No |
| 9004 | 2207052 | The media could not be fetched from this uri: {uri} | Instagram could not download the file from the address you gave it. | Make sure the URL is valid and open to the public. | No, fix the URL first |
| 100 | 2207028 | Your post won't work as a carousel. | The carousel has the wrong number of items. The message says 2 to 10, while Meta's publishing guide allows up to 20. | Send a number of photos and videos Instagram allows. | No |
| 100 | 2207023 | The media type {media-type} is unknown. | The media_type value is not one Instagram expects. | Send a valid media_type. | No |
| 100 | 2207040 | Cannot use more than {max-tag-count} tags per created media. | The post has more than 20 @ tags. | Use fewer tags. | No |
| 1 | 2207057 | Thumbnail offset must be greater than or equal to 0 and less than video duration | The cover-frame offset falls outside the video. | Set an offset, in milliseconds, inside the video's length. | No |
Meta's reference also lists three product-tagging subcodes (2207035 to 2207037) and a group for its ads audio API (9050 to 9064). They are about shopping tags and ad audio, not about whether a post goes out, so they are left off this page.
Which Instagram errors are safe to retry
Publishing to Instagram happens in two steps: you create a media container, then you publish it. That split decides what is safe to repeat.
- A failure while creating the container has published nothing. Creating it again cannot produce a second post. The download timeout and the failed container (2207003, 2207032) belong here. A server error (2207001) can come from either step.
- A failure that asks you to wait is retried against the same container. For 2207027, Meta recommends reading the container's status once a minute for no more than five minutes and publishing when it reads
FINISHED. A status ofERRORorEXPIREDmeans that container will never publish, and a container expires if it is not published within 24 hours. - A refusal about the file, the caption, the permission or the account fails the same way every time. Change what the table says to change, then send a new request.
- A publish call that times out with no answer has no code at all. Before you publish again, read the container's
status_code.PUBLISHEDmeans the post already went out and there is nothing left to retry.
The wider rule, with retry budgets and what to do about unknown outcomes on any network, is in our guide to publishing retry rules.
The publishing cap behind subcode 2207042
Meta's documentation gives two figures for the cap. Its publishing guide says an account is limited to 100 API-published posts within a 24-hour moving period, with a carousel counting as a single post. The reference for the limit endpoint, and the carousel section of the same guide, say 50.
Rather than hard-code either number, ask Instagram. GET /<IG_ID>/content_publishing_limit returns quota_usage, the number of posts published in the window, and config.quota_total, the ceiling for that account. Check it before a large batch and you will not meet 2207042 halfway through.
Sign-in and permission errors need the account owner
Code 190 cannot be fixed from your code. The token is gone, and only the person who owns the Instagram account can issue a new one by signing in again. Treat it as a state of the connection, not of the post: stop sending to that account, tell the owner, and send the missed posts once it is reconnected.
Code 10 and the 200 range mean the token still works but lacks a permission. Publishing needs instagram_business_basic and instagram_business_content_publish on the Instagram Login route, or instagram_basic, instagram_content_publish and pages_read_engagement on the Facebook Login route. The account type and Facebook Page each route depends on are covered in Instagram API publishing: accounts, Pages and breaks.
One caution from our own logs. On 6 November 2026 a Reel came back with code 10, subcode 2207081 and the usual permission message. It had been sent as a trial Reel from an account with too few followers, which Instagram does not allow, so reconnecting would have changed nothing. A handler that reads the word "permission" and asks for a reconnect gets this wrong, and one that reads the subcode gets it right.
What PostWharf shows when Instagram refuses a post
With PostWharf you do not handle these codes yourself. You send one post to the Instagram scheduling API, and every network it goes to gets its own row on the post's delivery receipt.
- A refused row says why, in a sentence, and what to do next. For the trial Reel above, it says the account does not have enough followers yet for trial Reels and tells you to post it again as a normal Reel.
- Only failures in transit are sent again. Failures in transit are retried with backoff. A rejection is not, because it would fail the same way on the third attempt.
- A dead sign-in is flagged, not retried. When Instagram revokes a sign-in, the channel is flagged and the owner is emailed to reconnect it, and the same failing request is not sent again.
- A caption that is too long never reaches Instagram. Captions are checked against the 2,200-character limit when the post is created, so a long one is refused up front.
- A post that reached your other networks but not Instagram is marked
partial, not published.
The same detail is on the API. GET /v1/posts/:id returns a delivery per channel with its status, attempts, live URL and error text, and a failure event carries an action field naming what to do. PostWharf's own API errors are a separate and much shorter list, a JSON error field with an HTTP status from 401 to 503, set out in the API reference. For failures on every network rather than Instagram alone, start with social media publishing API errors and fixes.
A workspace is one brand, with its own channels and API key, and the API comes with every plan.
Sources consulted: Meta for Developers (developers.facebook.com): Instagram Platform error codes, updated 2 June 2026 · Meta for Developers (developers.facebook.com): Publish content · Meta for Developers (developers.facebook.com): Content publishing limit · Meta for Developers (developers.facebook.com): Graph API error handling · All four were read on 10 November 2026. Check them again before you hard-code a rule.
Common questions
What does Instagram API error code 190 mean?
Code 190 means the sign-in has stopped working. It cannot be fixed from your code: only the person who owns the Instagram account can issue a new token by signing in again, so stop sending to that account and tell the owner.
What does Instagram error subcode 2207042 mean?
Subcode 2207042 means the account has used up its publishing allowance. Meta's documentation gives two figures for that cap, 100 and 50 API-published posts within a 24-hour moving period, so read the account's content publishing limit before a large batch instead of hard-coding either number.
Which Instagram API errors are safe to retry?
Only a few: a download timeout, a server error and media that is not ready yet are worth sending again unchanged. A refusal about the file, the caption, the permission or the account fails the same way every time, so change what the error names and send a new request.
PostWharf is priced per workspace rather than per connected channel, and every plan carries unlimited channels. See per-brand pricing.