Social media API error handling: a practical taxonomy
A practical way to classify social platform API errors — retryable vs. not, auth vs. content vs. rate-limit — instead of pattern-matching on message strings.
Classify errors by what to do next, not by which provider sent them. Two axes cover nearly everything: is it retryable, and which category — auth, content, rate-limit, or infra. Retry only when a structured signal says retryable, with backoff, jitter, and the same idempotency key, and classify each delivery target independently instead of treating a post as one pass/fail.
Publish to five social platforms through five separate provider SDKs and you inherit five separate error vocabularies — Meta's numeric codes and subcodes, TikTok's string error codes, LinkedIn's HTTP status plus a free-text message field, and so on. The instinct is to write a catch block that inspects each raw message and branches on substrings. That approach breaks the moment a provider rewords a message, localizes it, or ships a new subcode you have not seen before. A practical taxonomy — sorted by what the error means for your next action, not by which provider sent it — survives all three.
PostGate handles OAuth, publishing and delivery evidence for every network through one API. Start free or read the docs.
Why classify by what to do next, not by provider?
Every social platform error ultimately falls into one of a small number of operational buckets: the request is retryable as-is, the request needs different content, the connection needs the customer to reconnect, or the platform itself is temporarily or permanently unavailable for this action. Everything else — the exact wording, the provider's internal code numbering scheme, which HTTP status they happened to pick — is presentation detail that should not drive your control flow.
Building the taxonomy around outcome instead of provider means one decision tree handles Instagram, TikTok, LinkedIn, and every platform you add later, instead of a growing pile of provider-specific if branches that someone has to maintain forever.
What are the two axes that matter?
The two questions worth answering for every error, before anything else:
- Is it retryable? A transient provider outage or a rate limit resolves on its own and a retry (ideally with backoff) can succeed. An invalid access token or a content policy rejection will fail identically on every retry until something changes.
- What category is it? Auth (the connection or token is the problem), content (the post body or media is the problem), rate-limit (you are being throttled), or infra (the provider itself is degraded). Each category implies a different fix and a different audience — content errors go back to whoever wrote the post, auth errors need the customer to reconnect, infra and rate-limit errors are usually invisible to the end user if your system backs off correctly.
Cross those two axes and you get a small, finite grid. Almost every provider error you will ever see lands in one of its cells.
PostGate's structured envelope as a worked example
Rather than exposing each provider's raw error shape, PostGate normalizes every failure into one stable error envelope: a machine-readable code, a human-readable message, the platform when relevant, a boolean retryable, optional structured details, and a request_id for support correlation. The category lives in the code itself, not in text you have to parse.
{
"error": {
"code": "platform_transient",
"message": "Instagram is temporarily unavailable.",
"platform": "instagram",
"retryable": true,
"details": {},
"request_id": "req_01JXYZ"
}
}How do the codes map onto the grid?
PostGate's codes already sort onto the taxonomy above: media_invalid and platform_content_rejected are content errors — a different asset or different copy is needed, retrying the identical request will not help. profile_disconnected is an auth error — the connection needs reconnection, not a retry. platform_not_configured means the provider is unavailable in this workspace entirely, which is a configuration problem, not a transient one. rate_limited and platform_transient are the two codes marked retryable — a throttle and a provider outage, respectively, both of which can succeed on a later attempt with no other change.
Notice that "retryable" cuts across categories rather than defining one — it is the other axis, applied independently to whichever category the error falls into.
What does retryable actually mean operationally?
Retry only when retryable is true, reuse the same Idempotency-Key for a logical post, and apply exponential backoff with jitter rather than hammering the endpoint immediately. PostGate already retries provider delivery internally; a client-side retry is for API transport and acceptance failures, not a substitute for that internal delivery retry.
Just as important: do not recreate a failed target automatically. Inspect the target's evidence first — content rejection and reconnect errors need a change or customer action, not more identical requests fired at a connection or asset that will reject them every time.
Why read targets, not just the aggregate?
A single social post can fan out to several destinations, and each one can fail for a different reason from the same category grid. PostGate's targets array carries per-target status — published, failed, skipped, or awaiting_reconnect — so a partial aggregate result (some targets published, some did not) never collapses into one ambiguous error. Classify and act on each target independently, using the same retryable/category grid, instead of treating the whole post as a single pass/fail outcome.
Frequently asked questions
Why is parsing error message strings from social APIs a bad idea?
Because a catch block that branches on substrings breaks the moment a provider rewords a message, localizes it, or ships a new subcode you have not seen before. The exact wording, internal code numbering, and choice of HTTP status are presentation details. A stable machine-readable code and a retryable boolean survive all of that — which is why PostGate's envelope puts the category in the code itself.
Which PostGate error codes are retryable?
rate_limited and platform_transient are the two codes marked retryable — a throttle and a provider outage, both of which can succeed on a later attempt with no other change. media_invalid and platform_content_rejected are content errors needing a different asset or copy; profile_disconnected is an auth error needing reconnection; platform_not_configured is a configuration problem, not a transient one.
What categories do social media API errors fall into?
Four: auth (the connection or token is the problem), content (the post body or media is the problem), rate-limit (you are being throttled), and infra (the provider itself is degraded). Each implies a different fix and a different audience — content errors go back to whoever wrote the post, auth errors need the customer to reconnect, and infra and rate-limit errors are usually invisible to the end user if your system backs off correctly.
How should I handle a post that fails on some platforms but not others?
Read the targets array, not just the aggregate status. Each destination carries its own state — published, failed, skipped, or awaiting_reconnect — so a partial result never collapses into one ambiguous error. Classify and act on each target independently using the same retryable/category grid, instead of treating the whole post as a single pass/fail outcome.
