Skip to content
Docs · Start here

Errors & rate limits

Every error is JSON with an error sentence you can show a person, and often a code a program can branch on. What each status and code means, and what to do.

View as Markdown
All topics
On this page

Errors come back as { "error": "…", "code"?: "…", …details }. The sentence says what happened and what to do; the code is stable for programs. Nothing is charged for a refused request; the one exception is an AI model that used its whole token budget without answering (budget_exhausted, see AI Gateway).

Status codes

StatusMeaning
400The request is wrong: a missing field, a bad value, or a SQL mistake (the database's own message, cleaned).
401No credential, or it is invalid or revoked.
402Money or plan: a plan count or usage allowance reached, the Balance or AI credit too low, or the spending limit reached.
403The credential may not do this: role, read-only key, project key, owner-only money action, a paused or unverified account.
404Not found — or it belongs to another workspace.
409The resource is in the wrong state: still being created, disabled, or a delete blocked by money or work in flight.
410A database that no longer exists on the edge.
413Too large: an upload over the size cap, or AI input over 200,000 characters.
422Refused on purpose: a suppressed email address, or an AI answer that used the whole token budget with nothing to show.
429Too many requests. Wait Retry-After seconds.
501Not available yet (for example, a Postgres database or an image media asset).
502Something upstream failed: a delivery provider refused, or a delete could not finish (it is safe to retry).
503Temporarily unavailable. Retry after the Retry-After header when there is one.

Codes

CodeStatusMeaning and fields
plan_limit402 / 429A plan count, the email quota or a memory quota is reached, or the plan does not include the service (required_plan names the plan that does). limit, current; a memory quota adds limit_name (memory_items_per_store or memory_bytes_per_workspace). As a 429: more agent runs at once than the plan allows.
usage_limit402Hobby: the plan's file storage, database storage or build minutes are used up, so uploads, writes that add data or deploys are refused. metric, limit, current, required_plan.
usage_paused402A paid workspace past its included usage that cannot pay for more: the Balance is empty, or the last charge did not fit the Balance or the monthly spending limit. metric, limit, current, balance_cents, add_funds_url.
insufficient_balance402The Balance does not cover a purchase. price_usd, balance_usd, shortfall_usd, add_funds_url, card_on_file.
ai_credits_exhausted402Included AI and the Balance are used up. available_usd, resets_on, buy_url.
ai_credits_insufficient402Some AI credit is left, but less than this request's estimate. Lower max_tokens, shorten the prompt, choose a cheaper model or add funds.
ai_request_too_large402One AI request may reserve at most $2 on hobby, $10 on pro, $10 on enterprise. Shorten it, cap the output or split the work.
spend_limit_reached402The workspace's monthly spending limit would be passed. spend_limit_usd, spent_this_month_usd, limits_url.
email_unverified402 / 403The workspace owner's email must be verified (Hobby vendor AI models, live payment links).
payouts_require_owner403Withdrawals, refunds, payout setup and adding or removing the card on file need the owner signed in to the dashboard.
ai_gateway_off / ai_model_off403The AI Gateway, or this model, is switched off for the workspace (Dashboard → AI Gateway).
origin_not_allowed403An auth pool refused a browser Origin that is not on its list.
browser_access_off403An auth pool's browser sign-in is turned off.
mail_paused / mail_suspended403Sending is paused by an admin, or suspended by the platform.
invalid_domain400A sending domain that is not a real domain you could own (a single word, a test domain, a Harakumo name).
invalid_from / invalid_reply_to400A From or Reply-To address that is not allowed; the sentence says which rule.
sender_name / reserved_subject400A sender name or subject that breaks the rules in Mail → Sender names; the sentence says which.
from_domain_not_added400A from address on a domain that is not a sending domain of this workspace. Add it first.
domain_claimed_elsewhere / domain_taken409The domain belongs to another workspace on Harakumo.
dns_hosting_off409A sending domain bought on Harakumo whose DNS hosting is off. platform_option says how to turn it on.
mail_not_ready409An auth pool cannot email codes: the app has no sender name recipients may see. Set one on the Mail page.
payments_disabled409The payment account is disabled; re-enable it on the project.
deletion_blocked409A delete is refused. blockers[] has one sentence per reason (earnings, a withdrawal, an open checkout, a running deploy, bought domains).
confirm_forfeit_required409Deleting a workspace would give up a positive Balance; send confirmForfeit: true to accept.
suppressed422The recipient is on the suppression list.
budget_exhausted422The model used its whole max_tokens budget without an answer. Those tokens are charged; raise max_tokens.
ai_request_refused400 / 413The model refused the request itself (a parameter, or its size). It was not sent to other models; nothing was charged.
rate_limited429A rate limit. retry_after; API quotas add limit and window_seconds.
ai_rate_limited429The AI per-minute limit. limit, window_seconds, retry_after_seconds.
daily_cap429The workspace's own daily email cap.
code_limit429An auth pool's codes asked for from the browser reached the pool's limit or the workspace's share of the email quota. Retry-After.
zone_limit / account_zone_limit429New DNS setups for today are used up: 10 per workspace, or 20 across the workspaces one person owns (that one carries retry_after).
delivery_failed502The mail provider refused the message; message has the reason.
provider_error502A sending domain could not be set up; nothing was saved. Try again in a minute.
ai_unavailable / ai_provider_error502No model could answer right now; nothing was charged. harakumo-1 fails over between vendors.
zone_capacity503Harakumo is not accepting new domain setups for a while; nothing was set up. Buying a domain is not affected.
teardown_incomplete502A delete left some resources behind; the project is kept as teardown_failed. Delete again to retry.
processor_errorvariesThe payment processor refused; the sentence says why.

Handling errors in code

SDK
import Harakumo, { HarakumoError } from '@harakumo/sdk';

try {
  await hk.databases.query(dbId, 'SELECT 1');
} catch (err) {
  if (err instanceof HarakumoError) {
    if (err.status === 429) { /* wait err.body.retry_after seconds, then retry */ }
    if (err.body?.code === 'plan_limit') { /* show err.message to the person */ }
  }
  throw err;
}