Skip to content
Metric VaultHelp Center
Open app

Error and status codes

Every machine-readable error code and HTTP status the platform returns, listed alphabetically, with cause, fix and whether it is safe to retry.

Last updated 2026-08-06

Summary#

Two lookups in one page. The first is alphabetical by code, for anyone reading a response body or a log line. The second runs the other way, from the message a customer can see on their screen back to the code behind it, for anyone on a support call holding a screenshot. Both are complete for the codes the platform emits.

Overview#

A failed request returns a human message and, when the failure came from a gate rather than from a handler's own validation, a stable machine code.

json
{
  "error": "This tool needs a paid plan. Free includes the 10 technical SEO tools; upgrade to Pro to unlock the rest.",
  "code": "upgrade_required",
  "current_plan": "free",
  "required_plan": "pro",
  "upgrade_url": "https://metricvaultai.com/pricing"
}

Three rules for reading one:

  • Branch on code, never on the message. Messages are translated in the interface and their wording changes; codes are stable.
  • code is often absent. Plain validation failures return error only. That is normal, not a malformed response.
  • A 200 is not always a success. A few endpoints report failure inside the body. They are listed near the end of this page.

Quota and plan failures carry extra structured fields. Quota responses add plan, used, quota, cost, reset_at, reset_date, days_until_reset and upgrade_url. Rate-limit responses add limit, used and reset_in_minutes. Plan gates add current_plan, required_plan and upgrade_url.

HTTP statuses#

StatusMeaning hereSafe to retry?
200Success, or a soft failure carrying ok: false. Check the bodyNot applicable
201Created. Blog sites and taxonomy items onlyNo
301Permanent redirect. Legacy public-tool paths onlyFollow it
400The request was wrong: a missing field, a bad value, an unsupported typeNo. Fix the request
401Not authenticated: no credential, or an invalid, expired or revoked oneNo. Fix the credential
403Authenticated but not allowed: wrong plan, wrong role, suspended account, wrong secretNo. Change the entitlement
404The resource does not exist, or does not belong to the callerNo
405Method not allowed. Blog site console onlyNo
409Conflict: already invited, or a newsletter already sentNo, unless you resend with force
410Gone. A share link past its expiryNo
413Payload too large. Blog media import onlyNo. Send something smaller
429Rate limited, or out of creditsYes, after the stated window
500An unhandled error inside a handler, or an upstream failureOnce
502An upstream fetch failed. Responsiveness analysis and Growth ActionsOnce
503A dependency is unavailable or unconfigured and the gate failed closedYes, with backoff
504An upstream fetch timed out. The responsiveness preview onlyOnce

Every administration route answers a failed authorisation with 403 and {"error":"Unauthorized"}, not 401.

Codes, A to Z#

codeHTTPWhat it meansCauseFixRetry
account_suspended403The account is suspendedAn administrator suspended it. Billing is not affectedContact supportNo
ai_not_configured503No AI provider key is set for this featureOperator configurationOperator actionNo
ai_unavailable503Every AI provider failed for this callUpstream outage or timeout during claim extractionWait and run againYes
already_sent409The newsletter for that post has already been deliveredA repeat sendSend again with force only if intendedNo
auth_required401The call needs an identified accountA metered run arrived with no account, or a recommendations request didSign in, or send the account addressNo
bad_form400The upload was not multipartWrong content type on a media uploadUse multipart/form-dataNo
bad_locale400The language code was not recognizedA malformed translation targetSend a two-letter code, optionally with a regionNo
bad_method405That method is not supported on this routeBlog site console onlyUse GET, POST or PATCHNo
bad_request400A required field was missing or a value was not allowedBlog writes without a site, role changes without both addresses, an attempt to assign the owner roleSend the missing field, or pick a valid valueNo
bad_type400Unsupported image typeBlog media uploadUse PNG, JPG, WEBP or GIFNo
blocked_host400The target host is not allowedThe address resolved to a private, loopback, link-local or reserved networkPoint at a public hostNo
blog_not_configured503Blog publishing is not configured in this environmentOperator configurationOperator actionNo
create_failed400The item could not be createdA taxonomy item or author created without a nameSend a nameNo
email_not_configured503Email delivery is not configuredThe email provider key is missingOperator actionNo
forbidden403Allowed to sign in, not allowed to do thisA blog role lacks the capability, an owner-only blog action, or a diagnostic route called without the internal keyAsk the owner to raise your role, or supply the correct keyNo
hourly_rate_limit429The hourly fair-use ceiling was reachedMore than 100 light-tool calls in one clock hourWait for reset_in_minutesYes
media_not_configured503Image storage is not connectedThe object store is not boundOperator actionNo
no_customer400No subscription exists for this addressThe address has never subscribedSubscribe firstNo
no_file400The upload contained no fileThe multipart body had no file partAttach the fileNo
no_recipients400None of the addresses given are confirmed subscribersA newsletter aimed at unknown addressesCheck the listNo
no_sentences400No checkable sentences were foundThe text was fragments rather than proseSend proseNo
no_session401The blog API could not identify the callerNo account address on the requestSend the account addressNo
no_subscribers400The site has no confirmed subscribersNothing to send toCollect subscribers firstNo
not_configured503A provider this feature needs is not configuredPlagiarism checking needs search-data credentials; Fact Check needs the research provider keyOperator actionNo
not_found404The target does not existAn unknown id, a non-member, or an unknown sub-routeCheck the identifierNo
not_published400The post is still a draftA newsletter was requested for an unpublished postPublish it firstNo
plan_check_failed503The plan lookup failed, and the gate failed closedA dependency was briefly unavailable. Nothing ran and nothing was chargedRetry with backoffYes
portal_not_configured503The billing portal has no configuration and could not be createdOperator configurationOperator actionNo
post_not_found404No such public postThe slug is wrong, or the post is not livePublish it, or check the slugNo
quota_check_failed503The usage lookup failed, and the gate failed closedA dependency was briefly unavailable. Nothing ran and nothing was chargedRetry with backoffYes
quota_exceeded429The month's credit allowance is spent, or the plan has noneA premium run on an exhausted or zero allowanceWait for reset_date, or upgradeNot until reset
reco_quota_exceeded429The month's AI recommendations allowance is spentToo many Get recommendations requests this monthWait for the reset, or upgradeNot until reset
reco_upgrade_required403Recommendations need a higher planPro and above by defaultUpgradeNo
same_locale400The translation target equals the sourceThe post is already in that languagePick another languageNo
seat_check_failed503The seat count could not be read, and the gate failed closedA dependency was briefly unavailableRetryYes
send_failed503The email provider rejected the batchUpstream refusalRetryYes
site_not_found404No such blog siteWrong site id or slugCheck the identifierNo
stripe_not_configured503Billing is not configured in this environmentThe billing key is not setOperator actionNo
stripe_error503 or 400The billing provider returned an errorPassed through from the providerRead the message; retry only for a transient errorSometimes
subscribe_failed400The subscription address failed validationA malformed email addressCorrect the addressNo
too_large400 or 413The payload exceeded its ceilingA media upload over 5 MB, or an import over 15 MBSend something smaller. See All limits and quotasNo
too_short400There was not enough text to checkFewer than 25 words sent to the plagiarism or fact checksSend more textNo
upgrade_required403The plan is below the feature's minimumA Free account ran a tool that costs credits, a feature needs a specific tier, or the plan has no team seatsUpgrade. required_plan names the tierNo
webhook_not_configured503The billing webhook signing secret is missingOperator configurationOperator actionNo

From the message on screen back to the code#

The messages a customer is most likely to read out or screenshot, and what they mean. Quoted exactly.

MessageCodeHTTPWhat actually happened
Please sign in to run this.auth_required401A run that costs credits arrived without an account
Please sign in to use recommendations.auth_required401Same, from the recommendations panel
This account is suspended. Please contact support.account_suspended403The account was suspended by an administrator
This tool needs a paid plan. Free includes the 10 technical SEO tools; upgrade to Pro to unlock the rest.upgrade_required403A Free account ran a tool that costs credits
This feature requires the <Tier> plan. Your account is on <Plan>. Upgrade to unlock it.upgrade_required403A tier-gated feature: scheduled reports, white-label branding or API keys
Team invites require the Pro plan or higher. Your account is on Starter.upgrade_required403The plan carries no invite allowance. It names Starter even on Free
Team seat limit reached (<cap> members on the <Plan> plan). Upgrade for more seats.upgrade_required403Every seat is taken, pending invites included
AI recommendations are available on the <Plan> plan and above. Your account is on <Plan>. Upgrade to turn any result into a step-by-step action plan.reco_upgrade_required403Recommendations need Pro by default
You've used all <N> premium reports on the <PLAN> plan this month. Light tools (keyword research, SERP, content, technical audits) keep working. Quota resets on <date> (<in N days>). Upgrade to continue using premium reports now.quota_exceeded429The month's allowance is spent
Premium reports aren't included on the <PLAN> plan. Light tools (keyword research, SERP, content, technical audits) stay free. Upgrade to a paid plan to run premium reports.quota_exceeded429The plan's allowance is zero
You've used all <N> AI recommendations on the <PLAN> plan this month. Your quota resets on <date> (<in N days>). Upgrade to get more right away.reco_quota_exceeded429The recommendations allowance is spent
Hourly fair-use limit reached (100 light-tool calls/hour). This protects our infrastructure from abuse while keeping your monthly usage unlimited. Please wait ~<N> minutes for the next hourly reset.hourly_rate_limit429Over 100 light calls in one clock hour
Usage check temporarily unavailable, please retry.quota_check_failed503The usage lookup failed. Nothing was charged
Plan check temporarily unavailable, please retry.plan_check_failed503The plan lookup failed. Nothing was charged
Could not verify your team seat limit, please retry.seat_check_failed503The seat count could not be read
This tool is temporarily unavailable. Please try again shortly.(none)503An operator switched that specific tool off
Paste at least a couple of sentences to check.too_short400Fewer than 25 words
Fact-checking is not configured (the Perplexity key is not set).not_configured503The research provider key is missing
Weekly scheduling is available on paid plans. Upgrade to schedule automatic reports.upgrade_required403Scheduled reports need Starter or above
Billing is not configured yet.stripe_not_configured503The billing key is not set in this environment
No subscription found for this account yet.no_customer400The address has never subscribed
Key limit reached (5 active keys). Revoke one first.(none)400Five API keys already exist
Job not found or expired. Please re-submit.(none)404A background article job older than an hour
That host is not allowed(none)400The address resolved to a private or reserved network
Invalid tool type: <type>(none)400An unrecognized tool id, rejected before anything is charged

Error message reference carries the wider set of interface messages, including the ones that never reach an API response.

Failures without a code#

Plain validation failures return error only. They are grouped by feature in Error codes, which is the endpoint-by-endpoint catalogue. The families are:

FamilyTypical shape
Missing fieldsuser_email and member_email required, user_email, domain, keyword required
Bad tool inputMissing type, Missing url, Invalid URL, Only http(s) URLs are allowed
Size ceilingsReport too large — max 2MB, Too many strings (max 100 per request)
Team conflictsYou can't invite yourself., Already invited or this person is already a member.
Upstream fetch failuresThe responsiveness analyzer's five 502 messages
Model failuresFailed to parse AI response, plus five friendly rewrites of provider errors
AdministrationUnauthorized, Only an owner can manage customers., Unknown plan.

Failures reported with HTTP 200#

Three places report a failure inside a successful response. Check the body, not the status.

WhereShapeMeanings
Saving a run to the Library{"ok":false,"reason":"<reason>"}missing_fields, no_db, unserialisable, data_too_large, failed
Saving a rendered report{"ok":false} or {"ok":false,"reason":"too_large"}The rendered HTML exceeded its ceiling
Pushing to a publishing target{"ok":false,"enabled":false,…}Publishing is not enabled yet and always refuses

Checking for an existing saved result also always returns 200, with {"found":false} when nothing matches. That is not an error.

Thirty tools are marked as real-data tools and never invent numbers. When the provider has nothing they return 200 with noDataAvailable: true and the message No measured data was found for "<query>". This is a real-data tool, so Metric Vault shows nothing here rather than fabricating a number. Check the spelling, or try a more established domain, keyword or topic. That is a successful run with an honest empty result. See A tool returned no data.

Fail-open and fail-closed#

Knowing which way a gate falls tells you whether a 503 cost anything.

GateOn dependency failureResult
Plan checkClosed503 plan_check_failed. Nothing ran, nothing was charged
Credit quota checkClosed503 quota_check_failed. Nothing ran, nothing was charged
Recommendations quotaClosed503 quota_check_failed or 503 plan_check_failed
Team seat checkClosed503 seat_check_failed
Billing webhook signatureClosed503 webhook_not_configured when the secret is unset
Internal job secretClosed503 when unset, 401 when wrong
Hourly rate limiterOpenA limiter failure allows the call rather than blocking it
Translation providersOpenThe original string is returned untranslated
Notification preferencesOpenAll preferences default to on
Activity loggingOpenLogging never fails a request

Retry guidance#

SituationAction
503 with plan_check_failed or quota_check_failedRetry with exponential backoff. Nothing was charged
503 naming a missing provider or keyDo not retry. It needs an operator
429 with hourly_rate_limitSleep for reset_in_minutes, then retry
429 with quota_exceeded or reco_quota_exceededDo not retry. Wait for reset_date, or upgrade
500 from a model callRetry once. A second failure is worth reporting
502 or 504 from the responsiveness analyzerRetry once
401 or 403Never retry. Fix the credential or the entitlement
400Never retry. Fix the request
Note

Note: A retry after a 503 from a fail-closed gate cannot double-charge, because nothing was metered on the failed attempt. A retry after a 500 from a model call can, because the credit is taken before the model is called.

See also

Was this article helpful?