# Instagram API Error 2534022 & 10900: Fix 'Private Reply Window Expired' & 'Already Replied'

> How to fix Meta Graph API Error 2534022 (Private reply window expired), Error 10900 (Already replied to comment), and Ad comment DM failures on Instagram in 2026.

- **Canonical URL:** https://rapiddm.com/blog/instagram-error-2534022-private-reply-window-expired-fix
- **Author:** RapidDM
- **Published:** 2026-09-28T10:00:00+05:30
- **Updated:** 2026-09-28T13:15:00+05:30
- **Tags:** Instagram Graph API, Troubleshooting, Error Codes, Comment to DM

---

If you run Instagram Comment-to-DM automation—whether through your own webhook server, n8n, Make, ManyChat, or another Graph API tool—sooner or later your error logs will catch this response from Meta:

```json
{
  "error": {
    "message": "(#100) The comment cannot be replied to privately.",
    "type": "OAuthException",
    "code": 100,
    "error_subcode": 2534022,
    "fbtrace_id": "A9xK2..."
  }
}
```

Alongside **Error Subcode `2534022`**, teams building or debugging comment triggers frequently run into **Error `10900` (`This comment has already been replied to`)** and **Error Subcode `2534014` (`Message cannot be sent outside the allowed window`)**.

Because Meta's error string (`The comment cannot be replied to privately`) is used as a catch-all across five different failure conditions, diagnosing it from the message alone is frustrating. This guide walks through what the Private Reply endpoint enforces on Meta's servers, why each error subcode triggers, and how to fix your workflow or webhook handler.

## 1. What Meta's Private Reply API enforces on the server

When someone comments on your Instagram post or Reel, your app cannot message them using their regular `ig_scoped_id` unless they already have an open 24-hour DM conversation with your account. Instead, Meta requires your first automated message to be sent as a **Private Reply** referencing the specific `comment_id`:

```http
POST https://graph.instagram.com/v21.0/{ig-user-id}/messages
Content-Type: application/json

{
  "recipient": {
    "comment_id": "17984562839102938"
  },
  "message": {
    "text": "Hey! Tap below to grab the guide:"
  }
}
```

Meta enforces four strict server-side rules on this endpoint:

| Rule | Limit enforced by Meta | Error returned when violated |
| --- | --- | --- |
| Organic Post / Reel Window | Must send within 7 days (168 hours) of comment creation | code: 100, error_subcode: 2534022 |
| Instagram Live Window | Must send within 24 hours of the Live broadcast comment | code: 100, error_subcode: 2534022 |
| One DM Per Comment ID | Only 1 Private Reply allowed per unique comment_id | code: 10900 (Already replied) |
| Second / Follow-Up Message | Cannot send a 2nd DM unless the user replies or taps a button | code: 10, error_subcode: 2534014 |

## 2. Five root causes of Error Subcode `2534022` (and how to fix them)

### Cause A: Backfilling comments older than 7 days (168 hours)
A common scenario looks like this: you publish a Reel on Monday, it goes viral on Friday, and on the following Wednesday you connect an automation tool or run a script to message everyone who commented earlier. Any comment whose creation timestamp is more than 168 hours old fails immediately with `error_subcode: 2534022`.

**How to fix it:**
- In custom scripts or n8n workflows, check `Date.now() - commentTimestampMs < 7 * 24 * 60 * 60 * 1000` before calling `/messages`.
- For commenters older than 7 days, post a **public comment reply** (`POST /{comment-id}/replies`) instead: *"Hey! I just turned on the auto-DM for this Reel—drop the word GUIDE again in a fresh comment or DM me directly and it'll send right over."* Public comment replies do not expire after 7 days.

### Cause B: Commenters on unpublished "Dark Post" Instagram Ads
When media buyers build an Instagram ad inside Meta Ads Manager from scratch (*Create Ad* using uploaded video/copy) rather than boosting an existing organic Reel, Meta treats that ad creative as an unpublished "dark post." Comments on dark posts frequently fail when called against the standard organic Private Reply endpoint, returning `2534022` or `Unsupported post request`.

**How to fix it:**
1. Publish the Reel organically to your Instagram profile first (or select a high-performing organic Reel you already posted).
2. Inside Meta Ads Manager, go to the **Ad** level and change **Ad Setup** from *Create Ad* to **Use Existing Post**.
3. Select your Instagram Reel from the post picker (or paste its Instagram Post ID). Because the ad now shares the exact `media_id` of your published organic Reel, every comment triggers standard webhooks and supports the full 7-day Private Reply window.

### Cause C: Attempting to send two messages in a row using `comment_id`
Suppose you want your automation to send a greeting message first, wait three seconds, and then send a link card. If your workflow tries to call `POST /{ig-user-id}/messages` twice after a comment trigger, Message #1 succeeds and Message #2 fails with `10900` (if you pass `comment_id` again) or `2534014` / `2534022` (if you pass the user's `id` before they have replied).

**How to fix it:**
Meta does not open a two-way 24-hour messaging window just because you sent a Private Reply. The 24-hour window only opens **after the recipient replies to your Private Reply or taps a button/quick-reply inside it**.
- Put a **Postback Button** or **Quick Reply** on Message #1 (for example, *"Send me the guide"* or *"I'm following — unlock link"*).
- Listen for the `messaging_postbacks` webhook event when the user taps that button.
- Once they tap the button, your server now has an active 24-hour window on their `sender.id` (`ig_scoped_id`), allowing you to check their follower status, send Message #2, attach a voice note, or schedule a follow-up reminder.

### Cause D: The comment was deleted by the user before the queue processed it
During viral spikes where thousands of comments land in an hour, a user sometimes posts a comment with a typo (`"GUDE"`), deletes it ten seconds later, and posts a new comment (`"GUIDE"`). When your worker processes the webhook for the deleted comment ID, Meta returns `2534022` or `100 / 33` because the underlying comment object no longer exists.

**How to fix it:**
Treat `2534022` as a non-retryable terminal status in your job queue (`BullMQ`, `Celery`, or `SQS`). Never retry `2534022` with exponential backoff—retrying dead comment IDs burns through your [200 calls/hour API rate limit](/tools/instagram-api-rate-limit-calculator) and delays valid commenters waiting in your queue.

### Cause E: Commenter privacy settings block business messages
If a user has configured **Settings → Messages and story replies → Message controls → Other people on Instagram → Don't receive requests**, or if the account belongs to a minor in a restricted jurisdiction, Meta blocks the Private Reply and returns `2534022` or `2534037`.

**How to fix it:**
Pair your Private Reply with a public comment reply (*"Just sent it to your DMs! If you don't see it in Message Requests, send me a quick DM with the word GUIDE"*). When the user initiates a direct message to your inbox, Meta opens the 24-hour window regardless of their cold-request filter.

---

## 3. Fixing Error `10900`: "This comment has already been replied to"

When Meta returns Error `10900`, a Private Reply has already been dispatched for that specific `comment_id`. If you see `10900` in your logs unexpectedly, check two common causes:

| Symptom in logs | Why it happens | Permanent fix |
| --- | --- | --- |
| Your own worker logs 200 OK, then 10900 3 seconds later | Your webhook endpoint took too long to respond to Meta, or Meta delivered a duplicate webhook event. | Return HTTP 200 OK within 500ms before calling the Graph API, and deduplicate jobs in Redis using comment_id as the jobId. |
| Every single comment fails with 10900 immediately | Another app (ManyChat, LinkDM, or Meta Business Suite) is still connected to your Instagram account and replying first. | Revoke old tools under Instagram Settings → Website Permissions → Apps and Websites, and disable old Meta Business Suite rules. |

## How RapidDM handles these edge cases out of the box

If you are tired of debugging Meta webhook retries, token refreshes, and rate-limit drops in custom workflows, [RapidDM](/) handles the underlying Graph API mechanics automatically:

- **Idempotent `comment_id` deduplication** so duplicate Meta webhook deliveries never trigger double-sends or `10900` errors.
- **Two-step Postback and Ask-to-Follow flows** that transition commenters from the single-message Private Reply into a full 24-hour conversation window cleanly.
- **Redis rate-limit queuing** that paces viral traffic spikes under Meta's 200 calls/hour ceiling while staying well inside the 7-day Private Reply window.
- **Free plan included:** Test your flows with 1,000 free automated DMs per month before upgrading to Pro ($19/month, $11/month billed yearly, or ₹499/month in India).

## Frequently asked questions

### What causes Instagram Graph API Error Subcode 2534022?

Error subcode 2534022 (OAuthException code 100: 'The comment cannot be replied to privately') triggers when your automation tries to send a Private Reply DM outside Meta's allowed time window—either more than 7 days after an organic post comment, or more than 24 hours after an Instagram Live comment—or when a user comments on an unpublished Dark Post Ad.

### How long is the Instagram Private Reply window in 2026?

For standard organic Feed posts, Carousels, and Reels, Meta allows 1 Private Reply DM within 7 days (168 hours) of the comment timestamp. For Instagram Live broadcasts, the Private Reply window is 24 hours from the comment.

### What does Error 10900 ('Already replied to this comment') mean?

Meta allows only one automated Private Reply DM per unique comment_id. If a webhook fires twice, or if you have two tools (like ManyChat and a custom script) connected to the same Instagram account, the second request fails with Error 10900.

### Why do Private Replies fail with Error 2534022 on Instagram Ads?

Comments on unpublished 'Dark Post' ads created directly inside Meta Ads Manager do not always expose a standard organic media Private Reply window unless the ad uses an existing organic post ('Use Existing Post' / Post ID). Switching your ad creative to use an existing published Instagram Reel fixes the issue.
