Error Reference
Every error code SociaHive returns, what it means, and how to recover.
Every non-2xx response from SociaHive carries a stable code string. The string is more reliable than the HTTP status for branching logic — statuses can shift between adjacent codes (e.g. 422 vs 400) as we tighten validation, but the code value is part of the public API.
Shape
In the Node and Python SDKs, every non-2xx response throws a SociaHiveError whose .code field matches the table below.
Codes
| code | HTTP | When it fires | What to do |
|---|---|---|---|
auth_error | 401 | Missing, malformed, or invalid X-API-Key / OAuth bearer; key revoked; key lacks the required scope for this tool. | Confirm key is set, has the right scope, and hasn't been rotated. SDKs expose this via err.isAuthError. |
not_found | 404 | The requested resource (flow, post, account) doesn't exist OR is owned by a different user. | Check the ID. Note: 404 is also returned when a resource exists but isn't accessible to your key (no information leak about other users' data). |
invalid_input | 400 | Request body / query failed the input schema — wrong type, missing required field, bad format. | The details object lists the failing fields. Fix the payload and retry. |
validation_error | 422 | Input parsed but a business rule rejected it (e.g. scheduling a post in the past, applying a tag with reserved characters). | Read details.reason for the specific rule violated. Not retriable without changing the input. |
conflict | 409 | Unique-constraint collision — e.g. a webhook subscription with the same target_url already exists, or two flow nodes share an ID. | Either update the existing resource or pick a different identifier. |
keyword_conflict | 409 | A keyword you're trying to register on a flow trigger is already claimed by another active flow on the same account. | Either deactivate the other flow, pick a different keyword, or scope to a specific post. |
state_error | 409 | The resource is in a state that can't accept this operation. Common case: editing nodes on a published flow. | For published-flow edits: duplicate_flow → edit the draft copy → activate_flow. The error's details usually carries a suggestion field. |
tier_error | 402 | Your subscription tier doesn't include this feature — e.g. randomizer nodes on the Free plan, or live-chat tools without Pro+. | Upgrade the plan or remove the feature from the flow. details.required_tier tells you the minimum. |
limit_reached | 422 | A counted resource has hit its tier cap — webhook subscriptions, connected accounts, scheduled posts per month, etc. | Either delete an existing resource of the same kind or upgrade the plan. |
no_account_selected | 400 | A flow / analytics tool needs a specific connected account context but the agent didn't supply one (only happens via MCP). | The chat-header account pill should auto-fill this; if it doesn't, pass account_id explicitly. |
rate_limit | 429 | You exceeded the per-minute or daily quota. | Honor Retry-After (seconds). The response details.window tells you which bucket tripped (read / write / expensive / daily). See Rate limits. |
upstream_error | 502 / 503 | A platform we depend on (Instagram, Meta, OpenAI, etc.) returned an error or timed out. | Usually transient — retry with exponential backoff. The details.upstream field names the platform. |
unknown_error | 500 | Something we didn't anticipate. | Retry once. If it persists, file an issue with the details.request_id value. |
Special envelope: pending_confirmation
Destructive tools (delete_*, publish_post_now, disconnect_account) don't error on the first call — they return a confirmation envelope:
Pass __confirmToken back on the second call within 5 minutes. See the Confirmation Flow section in the MCP setup guide.
SDK helpers
Convenience flags in the SDKs
Both Node and Python SDK error classes expose pre-computed flags for the codes you'll branch on most often:
err.isAuthError— true forauth_errorerr.isRateLimited— true forrate_limiterr.isNotFound— true fornot_founderr.isStateError— true forstate_errorandconflict
Use these instead of string-matching err.code when you can.
What's NOT in this list
- HTTP-only failures (e.g. 502 from Cloudflare before the request hits us) — no
codebecause they never reached the application. - Platform-side errors that we surface untransformed — see
details.upstreamonupstream_error.
If you hit a code that isn't in this table, file an issue with the response body — the table is the source of truth, but the codebase may have shipped a new code that hasn't propagated to docs yet.