Skip to content

Error codes ​

A developer hitting a TenkeyBridge error should never wonder what happened. Every fault carries three layers of help:

  1. The QBO-compatible Fault — the exact shape the QuickBooks Online API uses, so existing QBO SDKs and error handlers keep working unchanged. Branch on code.
  2. A tkb block — TenkeyBridge's enrichment: likely causes, concrete fixes, and a docsUrl deep-linking to that code's section on this page. It sits outsideFault, in a top-level field QBO clients ignore.
  3. A docs link in Detail — so even if your SDK only surfaces Message/Detail, the trail to the full story is still in front of you.

The fault envelope ​

jsonc
{
  "Fault": {
    "Error": [{
      "code": "UNSUPPORTED_BY_DESKTOP",
      "Message": "Unsupported by QuickBooks Desktop",
      "Detail": "Sparse update of Line is not supported yet for Bill; line-level updates are currently supported on sales forms (Invoice, Estimate, SalesReceipt, CreditMemo) only. Re-create the transaction or update header fields only. See https://docs.tenkeybridge.com/reference/error-codes.html#unsupported_by_desktop",
      "element": "Bill.Line"
    }],
    "type": "ValidationFault"
  },
  "time": "2026-07-24T00:00:00.000Z",
  "tkb": {
    "code": "UNSUPPORTED_BY_DESKTOP",
    "causes": [
      "The field, line type, item type, or operation you sent exists in QuickBooks Online but has no equivalent in QuickBooks Desktop's qbXML API — or the whole entity is a documented Desktop gap."
    ],
    "fixes": [
      "Remove or replace the unsupported value; the fault's element and Detail name exactly what triggered it.",
      "Check the entity's section on https://docs.tenkeybridge.com/compatibility/ for the full list of supported fields and operations."
    ],
    "docsUrl": "https://docs.tenkeybridge.com/reference/error-codes.html#unsupported_by_desktop"
  }
}
  • Fault.Error is always an array (currently always length 1); code is the value to branch on; element (when present) names the field that triggered the fault.
  • Fault.type is ValidationFault for anything you can fix by changing the request or the company file, SystemFault for TenkeyBridge-side failures (HTTP 5xx).
  • tkb is additive and versioned with the codes themselves (ERROR_CODES_VERSION = "2026-07"). Never required for correct handling — branch on code; read tkb when a human needs to know what to do next.

The string codes below are TenkeyBridge's own, part of the public API surface — their meaning won't change under you between versions. Numeric codes carry the same meaning they have in the QuickBooks Online API.

Translation codes ​

Raised when a request can't be translated honestly to QuickBooks Desktop. These are almost always fixable by changing the request.

UNSUPPORTED_BY_DESKTOP ​

HTTP 422 · You sent a field, line type, item type, operation, or whole entity that has no QuickBooks Desktop equivalent.

Causes

  • The field or operation exists in QuickBooks Online but qbXML (Desktop's API) has no way to express it — a permanent platform gap, not a missing TenkeyBridge feature.
  • The entity itself is a documented gap (Attachable, Budget, …) or not yet shipped in TenkeyBridge. Entity-level responses link straight to that entity's section on the compatibility page.

Fixes

  • Remove or replace the value — the fault's element and Detail name exactly what triggered it.
  • Check the entity's section on the compatibility page for the full list of supported fields and operations, and the closest supported alternative.
  • For Desktop-backed realms, branch on this code and degrade gracefully (skip the feature) rather than retrying — the same request will fail the same way every time.
jsonc
{
  "Fault": {
    "Error": [{
      "code": "UNSUPPORTED_BY_DESKTOP",
      "Message": "Unsupported entity",
      "Detail": "Item create/update lands in a later TenkeyBridge release. Pull items with read/query for now. See https://docs.tenkeybridge.com/reference/error-codes.html#unsupported_by_desktop",
      "element": "Item"
    }],
    "type": "ValidationFault"
  }
}

UNSUPPORTED_QUERY ​

HTTP 400/422 · Your query is valid QBO syntax, but TenkeyBridge can't answer it reliably.

Causes

  • A gateway-side filter, ORDERBY or COUNT(*) that would have to scan more than 5,000 records — 1,000 for transactions fetched with line items (TenkeyBridge fails loudly rather than return a possibly-incomplete answer). The Detail names the clause.
  • STARTPOSITION paging past what Desktop can serve for that query shape.
  • A QBO property Desktop has no equivalent for (the Detail names it).
  • A clause the entity doesn't take: CompanyInfo, Preferences and Budget accept only a bare SELECT * (and Id on Budget).

Fixes

  • Narrow the query with filters QuickBooks applies itself — a TxnDate or MetaData.LastUpdatedTime range, Active, Id, a CustomerRef / VendorRef, a name prefix — so the scan stays under the cap. See Query support for which conditions are pushed into QuickBooks and which are applied gateway-side.

UNMAPPED_FIELD ​

HTTP 422 · The payload contains a field TenkeyBridge doesn't recognize for this entity.

Causes

  • A typo in a field name, a QBO minor-version field, or a field that belongs to a different entity. Distinct from UNSUPPORTED_BY_DESKTOP: unmapped means "not a known field at all", unsupported means "known, but Desktop can't do it".

Fixes

  • Drop the field or fix the spelling; the entity's field table on the compatibility page lists every accepted field.

UNMAPPED_ACCOUNT_TYPE ​

HTTP 422 · The AccountType (or AccountSubType) value has no QuickBooks Desktop account-type equivalent.

Fixes

  • Use one of the Desktop-mappable account types listed in the Account section of the compatibility page; the fault's Detail names the closest supported type when there is one.

MISSING_REQUIRED_DESKTOP_ITEM ​

HTTP 422 · You referenced something QuickBooks Desktop models as an item in the company file, but the request doesn't point at one that exists.

Causes

  • Most commonly a bare-percentage or amount-off discount with no ItemRef — Desktop discounts are discount items; there is no "anonymous discount".

Fixes

  • Create the item in the Desktop company file, then reference it (e.g. DiscountLineDetail.ItemRef, by value = ListID or name = the item's full name). TenkeyBridge does not choose a default discount item for you.

Warnings ​

Non-fatal conditions come back on a successful response as an X-TKB-Warning header (printable ASCII, capped at 500 characters, several warnings joined with ; ). They are never sent on error responses. See Warnings.

  • QuickBooks warning <code>: <message> when QuickBooks Desktop performed the request but answered with a warning-severity status for part of it, for example QuickBooks warning 530: The field "Name" is not supported by this implementation.
  • TxnTaxDetail.TotalTax ignored; QuickBooks Desktop computed <amount> on Invoice, SalesReceipt, Estimate and CreditMemo create/update when you sent a TotalTax (without a TxnTaxCodeRef) that differs from the tax Desktop computed. Not emitted for /batch items.

Gateway codes ​

Raised by the TenkeyBridge gateway before or after translation — routing, auth, and the connection to the agent running next to QuickBooks Desktop.

NOT_FOUND ​

HTTP 404 · The URL doesn't match any TenkeyBridge route, or the entity segment isn't a known QuickBooks entity name at all (typo / unknown string). Known-but-unsupported entities return UNSUPPORTED_BY_DESKTOP instead.

Fixes

  • Check the path shape (/v3/company/{realmId}/{entity}) and the entity spelling against the entity matrix.

AUTHENTICATION_FAILED ​

HTTP 401 · The Authorization header is missing, isn't a Bearer token, or the access token is invalid or expired.

Causes

  • Access tokens live 60 minutes — the most common cause is simply an expired token.

Fixes

  • Send Authorization: Bearer <access_token>.
  • When the access token expires, exchange your refresh token at /oauth2/v1/tokens (grant_type=refresh_token) for a fresh pair — and store the new refresh token; refresh tokens rotate on every use.

AUTHORIZATION_FAILED ​

HTTP 403 · The access token is valid but was issued for a different realm than the one in the URL path.

Fixes

  • Use the realmId returned in your OAuth callback together with the tokens minted for it — realm and token travel as a pair.
  • If you meant to talk to a different company file, run the connect flow again for that realm.

RATE_LIMITED ​

HTTP 429 · This company (realm) sent more REST requests than the per-minute limit allows.

Every response on this surface — limited or not — carries three headers so you can see your budget before you hit it:

HeaderMeaning
RateLimit-LimitRequests allowed per minute for this realm.
RateLimit-RemainingRequests left in the current window.
RateLimit-ResetSeconds until the window resets.

A 429 additionally carries:

HeaderMeaning
Retry-AfterSeconds to wait before retrying (an integer, always ≥ 1).

Causes

  • This company (realm) sent more REST requests than the per-minute limit allows.

Fixes

  • Wait for the number of seconds in Retry-After, then retry.
  • Watch RateLimit-Remaining on ordinary responses and back off before it reaches 0, rather than polling at the edge of the limit.
  • Batch or page requests instead of polling in a tight loop; use CDC for change-tracking instead of repeated full queries.

The OAuth token/authorize endpoints and the portal sign-in endpoints enforce their own, separate per-IP limits — see OAuth errors for the slow_down shape returned there. Both carry the same four headers.

QUERY_PARSER_ERROR ​

HTTP 400 · The query parameter is missing or empty.

Fixes

  • Pass a QBO-SQL statement in the query parameter, URL-encoded: GET /v3/company/{realmId}/query?query=SELECT%20*%20FROM%20Customer.

BAD_REQUEST ​

HTTP 400 · The request doesn't form a valid operation.

Causes

  • A non-JSON request body, an unsupported ?operation= value, or an update/delete without the record's Id.

Fixes

  • The Detail names the exact problem; correct the request shape and resend. Updates and deletes need a JSON body carrying the entity's Id (and SyncToken).

AGENT_OFFLINE ​

HTTP 503 · Nothing is serving this realm right now — no agent connected and no Web Connector polling. The gateway raises this only before sending a request; a request lost after it was sent is a 504 AGENT_TIMEOUT.

Causes

  • The Windows machine hosting QuickBooks Desktop is off or asleep, the agent isn't running, or its network path to the gateway is down.
  • Over Web Connector: Web Connector isn't running on the QuickBooks machine, Auto-Run is off for this entry, or the hosted-desktop session disconnected.

Fixes

  • Start the agent on the machine hosting QuickBooks Desktop and retry — requests succeed as soon as it reconnects.
  • Over Web Connector: open Web Connector, tick Auto-Run on the TenkeyBridge entry, and wait one poll (~10 s); see the Web Connector guide.
  • Nothing is queued: this request was not executed, so it's always safe to retry.
  • If the realm polls unattended (e.g. overnight), treat 503 as "come back later", not as a failure.

AGENT_TIMEOUT ​

HTTP 504 · The request was sent, but its answer never came back — QuickBooks didn't answer inside the request budget, or the connection was lost first. The code is the same for both transports; the Message says which one waited — "Agent for realm …" (60 s budget) or "Web Connector for realm …" (4-minute budget, because Web Connector may be cold-launching QuickBooks under the unattended grant).

Causes

  • A modal dialog open in QuickBooks on the host machine (the #1 culprit), a very large request, or the company file busy with another operation.
  • Over Web Connector: QuickBooks was closed and a hosted desktop took longer than the 4-minute budget to launch it (see the Web Connector guide).
  • The connection to the agent dropped, or the gateway restarted (usually a deploy), after the request was sent — the Message says the connection was lost or the gateway restarted.

Fixes

  • Dismiss any open dialog in QuickBooks on the host machine, then retry.
  • Break very large queries into pages.
  • ⚠️ The request may still have applied after the gateway gave up — re-query before retrying a write to avoid duplicates, or send the write with a requestid so the retry is safe (Safe retries).

QB_NOT_OPEN ​

HTTP 503 · The agent is connected, but QuickBooks isn't open in the Windows session the agent runs in, so the request was not executed. Raised by the edge agent (never by Web Connector) and only before anything is sent to QuickBooks — always safe to retry, writes included. If a Web Connector is also live for the realm, the gateway retries the request there automatically before returning this.

Causes

  • QuickBooks was closed, or the hosted-desktop (for example Rightworks) session was disconnected and reconnected without it.

Fixes

  • Open QuickBooks on the pinned company file in the same Windows session the agent runs in, then retry.
  • The agent can be configured to fail this way instead of launching QuickBooks itself (RequireQuickBooksRunning); see the Rightworks guide.
  • Nothing is queued: treat it like AGENT_OFFLINE — come back later.

VOID_APPLIED_READBACK_FAILED ​

HTTP 502 (per-item fault slot in a batch) · The void was applied in QuickBooks, but reading the voided record back failed, so the outcome of the read is unknown.

Causes

  • The agent went offline or timed out between the TxnVoidRq and the follow-up read.
  • The read-back response could not be translated.

Fixes

  • Do not retry the void — it already took effect, and a retry fails with a stale SyncToken (5010). GET /{entity}/{Id} to see the voided record.

CUSTOM_FIELD_UNKNOWN ​

HTTP 400 · A CustomField in the request names a field that is not defined in this QuickBooks company file, or that is defined but not assigned to this record type. Checked before anything is written, so nothing was saved.

Causes

  • A misspelled Name, or a custom field that only exists in QuickBooks Online / another company file.
  • A field defined for Customers being set on an Invoice (Desktop custom fields are assigned per record type).

Fixes

  • Define the custom field in QuickBooks Desktop (Lists > Customer & Vendor Profile Lists > Custom Fields, or the Sales form's Additional Info), tick the record type, and resend. Matching is case-insensitive. DefinitionId alone cannot identify a Desktop field — send the Name.

CUSTOM_FIELD_WRITE_FAILED ​

HTTP 502 (per-item fault slot in a batch) · The record was saved in QuickBooks, but writing one or more of its custom-field values failed afterwards. The fault names the record's Id, the fields that were applied and the ones that failed.

Causes

  • QuickBooks rejected a value, the agent went offline mid-request, or the field definition changed between the up-front check and the write.

Fixes

  • Do not retry the whole request: a create would duplicate the record. GET the record and send an update carrying only the failed CustomField entries.

CUSTOM_FIELD_READBACK_FAILED ​

HTTP 502 (per-item fault slot in a batch) · The record and all of its custom-field values were written in QuickBooks, but reading it back for the response failed.

Causes

  • The agent went offline or timed out after the writes, or the read-back could not be translated.

Fixes

  • Do not retry — everything was applied. GET /{entity}/{Id} to see the record.

PAYMENT_OUTCOME_UNKNOWN ​

HTTP 502 · QuickBooks answered a payment request with success but returned no payment record, so the outcome is unknown. Credits named in the request may have been applied.

Causes

  • A credit-only application (credit memos with a zero or omitted TotalAmt): Desktop applies the credit and creates no payment. TenkeyBridge refuses that request up front with a 422, so this 502 is a defensive backstop.

Fixes

  • Do not retry. GET the invoice and credit memo to see whether the credit was applied.
  • Apply credit memos together with a cash amount, or apply them in QuickBooks.

REQUESTID_INVALID ​

HTTP 400 · The requestid query parameter on a write is malformed. See Safe retries.

Causes

  • Empty, longer than 50 characters, or containing spaces, control characters or non-ASCII characters.
  • On /batch: longer than 36 characters, or an item bId longer than 10 characters (QuickBooks Online's own limits).

Fixes

  • Send a unique token of 1-50 printable ASCII characters without spaces; a UUID works.

REQUESTID_BODY_MISMATCH ​

HTTP 422 · This requestid was already used for a different request - a different body, entity or operation. Nothing was executed.

Causes

  • A requestid reused for a new write, or a retry whose payload changed between attempts.

Fixes

  • Use a new requestid for every new write; reuse one only to retry the exact same request.

REQUEST_IN_FLIGHT ​

HTTP 409 (with Retry-After) · A request with this requestid is still being processed. Nothing new was executed.

Causes

  • You retried while the original call was still running in QuickBooks.

Fixes

  • Wait Retry-After seconds and resend the same request with the same requestid; you will get the original result.

REQUEST_OUTCOME_UNKNOWN ​

HTTP 502 · The original request with this requestid was lost after it reached QuickBooks (a 504 AGENT_TIMEOUT or a dropped connection) and TenkeyBridge could not confirm whether it applied. The write is never re-sent.

Causes

  • The answer never came back, and the record could not be found (or, for updates, cannot be proven to be ours) on a re-read.

Fixes

  • Look the record up in QuickBooks (query by DocNumber or Id) and decide.
  • Retrying with the same requestid re-checks for free and returns the result as soon as it can be confirmed; if a late-running request applies after all, the next retry reports it.
  • See Safe retries.

AGENT_EXECUTION_ERROR ​

HTTP 502 · The request reached QuickBooks but failed at the QuickBooks/COM layer. The raw Windows-side error stays in the gateway logs (and the agent's, when one is in use), since it can contain machine-local detail.

Causes

  • QuickBooks isn't running, or no company file is open.
  • A QuickBooks login or authorization dialog is blocking access.
  • The agent and QBW.exe run at different Windows integrity levels — they must match (run both non-elevated).

Fixes

  • On the host machine: open QuickBooks with the company file, run both QuickBooks and the agent non-elevated, and check the agent log for the exact underlying error.
  • Over Web Connector: the error is recorded on the connector's row in the portal (the "last error" detail); QB_COMPANY_FILE_UNAVAILABLE there means the wrong company file is open — see Which company file.

INTERNAL_ERROR ​

HTTP 500 · An unexpected error inside the TenkeyBridge gateway — not your request and not QuickBooks.

Fixes

  • Retry once; if it persists, report it along with the response's time field so it can be correlated with the gateway logs.

SUBSCRIPTION_REQUIRED ​

HTTP 402 · This company's organization has no active TenkeyBridge subscription.

Causes

  • The organization's trial ended, or more than one realm is connected on the trial plan — trial accounts are limited to one realm.
  • A production subscription's payment lapsed and stayed unpaid past the 7-day grace period.

Fixes

  • Subscribe or manage billing for the organization in the TenkeyBridge portal — see the billing guide.
  • On a trial, each organization may connect at most one realm — upgrade to a paid plan to connect more.

SANDBOX_UNSUPPORTED ​

HTTP 400 · The sandbox doesn't emulate this request.

Causes

  • Reports and budgets (served from static captures in a later release), group item lines, or a query filter the sandbox doesn't implement. The fault's Detail names the request.

Fixes

  • Test that call against a real QuickBooks company file over the Web Connector.
  • Everything else keeps working in the sandbox; only this request is refused.

SANDBOX_DAILY_LIMIT ​

HTTP 429 · This sandbox used its REST calls for today (UTC).

Causes

  • More calls than the sandbox daily limit (2,000 by default) since 00:00 UTC.

Fixes

  • Wait for the reset at 00:00 UTC; Retry-After gives the seconds remaining.
  • In CI, reset the sandbox once per run and page with MAXRESULTS instead of polling.

SANDBOX_RECORD_LIMIT ​

HTTP 400 · The sandbox holds its maximum number of records.

Causes

  • A create would exceed the record limit (10,000 by default). Deactivated list records still count; deleted transactions don't.

Fixes

  • Delete transactions you no longer need, or reset the sandbox.

CDC_INVALID_ENTITIES ​

HTTP 400 · The entities parameter is missing, empty, or not a comma-separated list of QBO entity names.

Causes

  • No entities parameter, an empty one, or a value that isn't a comma-separated list (e.g. entities=Invoice,Customer,Bill).

Fixes

  • Pass entities as a comma-separated list of entity names. Unsupported names don't fail the request — they come back as per-entity Fault slots — but the parameter itself must be present and non-empty.

CDC_INVALID_CHANGED_SINCE ​

HTTP 400 · changedSince is missing, unparseable, or outside the 30-day CDC look-back window.

Causes

  • changedSince isn't a parseable ISO 8601 timestamp or YYYY-MM-DD date.
  • changedSince is older than the 30-day CDC look-back window — the same limit QuickBooks Online enforces; it also bounds worst-case Desktop query cost.

Fixes

  • Pass changedSince as an ISO 8601 timestamp (2026-07-01T00:00:00Z) or bare date (2026-07-01) within the last 30 days.
  • Syncing older data? Do a full walk with /query and a MetaData.LastUpdatedTime filter instead — CDC is for incremental polling.

CDC_OVERFLOW ​

HTTP 400 · More than 1,000 objects changed for one entity in the requested window.

Causes

  • A CDC slot never silently truncates, so once an entity crosses 1,000 changed objects in the window it returns this fault instead of a partial array.

Fixes

  • Shorten the changedSince window and poll more frequently.
  • Or walk this entity with /query using a MetaData.LastUpdatedTime filter plus STARTPOSITION/MAXRESULTS pagination — that path has no object cap.

BATCH_INVALID_REQUEST ​

HTTP 400 · The batch envelope or one of its items is structurally malformed.

Causes

  • BatchItemRequest is missing, empty, or not an array; a missing or duplicate bId; an item that isn't exactly one Query or one entity payload; a missing or unknown operation; or an operation/Id combination that contradicts itself (create with an Id, update/delete without one).

Fixes

  • Nothing executed — a malformed envelope never half-runs. The fault Detail names the offending item by bId or index; fix that item's shape and resend the whole batch.

BATCH_TOO_MANY_ITEMS ​

HTTP 400 · The batch carries more than 30 items.

Causes

  • More than 30 items in one batch — the same per-request cap QuickBooks Online enforces.

Fixes

  • Split the work into multiple batch calls of at most 30 items each. Items execute sequentially either way, so splitting costs no extra Desktop round trips.

BATCH_UNSUPPORTED_OPTION ​

HTTP 200 (per-item fault slot — the batch request itself is not a 400) · The item carries an unsupported optionsData value.

Causes

  • The item carries an optionsData value other than "void", or "void" on a create/delete item — only optionsData: "void" on an update item (QBO's spelling) is wired.

Fixes

  • Drop optionsData from the item, or for a void send operation: "update" with optionsData: "void" and the record's Id + SyncToken. Only this item faulted — the rest of the batch still ran.

REPORT_UNKNOWN ​

HTTP 422 · The report name in the URL is not one TenkeyBridge serves from Desktop.

Causes

  • The report name is not one of the 20 reports TenkeyBridge serves from QuickBooks Desktop. QuickBooks Online's report catalogue is larger; CashFlow in particular does not exist in QuickBooks Desktop's SDK (qbXML has no cash-flow report), and class/department/tax families are not shipped.

Fixes

  • Use one of the names in the fault detail (ProfitAndLoss, BalanceSheet, TrialBalance, GeneralLedger, TransactionList, the aged and balance reports, ...). Names match case-insensitively.
  • Check the compatibility page for the current report coverage before adding a new report call.

REPORT_UNSUPPORTED_OPTION ​

HTTP 422 · The request carries a report parameter Desktop cannot honour.

Causes

  • The request carries a QuickBooks Online report parameter that Desktop's report engine cannot honour — column selection, a filter or column split qbXML has no twin for (department, Employees / ProductsAndServices columns), an aging knob that lives in company-file preferences rather than the request, or accounting_method on a report Desktop refuses a ReportBasis for.

Fixes

  • Drop the parameter and read the standard Desktop layout; the fault's element names exactly which one failed.
  • For aging buckets, change them in QuickBooks under Edit > Preferences > Reports & Graphs — Desktop returns whatever the company file is configured with, as the report's columns.
  • For a filter or column split Desktop cannot express, fetch the report and narrow it client-side. Supported filters are customer, vendor, item and class (Ids); supported column splits are Total, Month, Week, Days, Quarter, Year, Customers, Vendors and Classes on the period summary reports.

REPORT_INVALID_DATE ​

HTTP 400 · A report date or date macro was not usable.

Causes

  • A report date was not a real calendar date in YYYY-MM-DD form, start_date and end_date were not supplied together, start_date fell after end_date, or date_macro was not one of QuickBooks Online's date macros.

Fixes

  • Send start_date and end_date together as YYYY-MM-DD, or send date_macro alone — not a partial pair.
  • For the aging reports use report_date (a single as-of date), not start_date/end_date.
  • Omit the dates entirely to get the fiscal year-to-date window, which is what the same call returns from QuickBooks Online.

Numeric codes ​

Numeric codes carry the same meaning they have in the QuickBooks Online API, so existing QBO error-handling logic keeps working unchanged. They come from three places: mapped from QuickBooks Desktop status codes when Desktop itself rejects the request (610, 5010, 6240, 2500, and 2020 from Desktop's 3070); raised by TenkeyBridge's own validation before the request ever reaches Desktop (2010, 2020, 2050, and 4000 for a query QBO's grammar rejects); and 500 for an internal TenkeyBridge failure.

610 — Object not found ​

HTTP 400 · No record with the given Id exists in the company file.

Causes

  • The record was deleted in QuickBooks, or the Id belongs to a different realm.
  • Desktop Ids differ from QBO Ids for the same logical record — an Id carried over from a QBO integration will never match.

Fixes

  • Re-query for the record to get its current Id in this realm.

5010 — Stale object ​

HTTP 400 · Optimistic-concurrency conflict: the SyncToken you sent is stale (Desktop's EditSequence).

Causes

  • A user or another integration modified the record in QuickBooks after you read it.

Fixes

  • GET the record again, take the fresh SyncToken, and re-apply your change.
jsonc
{
  "Fault": {
    "Error": [{
      "code": "5010",
      "Message": "Stale Object Error",
      "Detail": "QuickBooks Desktop: The provided edit sequence is out-of-date. See https://docs.tenkeybridge.com/reference/error-codes.html#5010"
    }],
    "type": "ValidationFault"
  }
}

6240 — Duplicate name exists ​

HTTP 400 · A list record with this name already exists.

Causes

  • Desktop names (Customer, Vendor, Item, …) must be unique per list — including inactive records, which is the case that usually surprises QBO-first integrations.

Fixes

  • Use the existing record, pick a different name, or rename/reactivate the conflicting record in QuickBooks.

2500 — Invalid reference ​

HTTP 400 · A *Ref you sent (CustomerRef, ItemRef, AccountRef, …) points at a record that doesn't exist in the company file.

Fixes

  • Query for the referenced record first and use its current Id; create it if it doesn't exist yet.

2010 — Invalid field value ​

HTTP 422 · A field value fails validation — wrong type, an unparseable date or number, or a value outside what Desktop accepts.

Fixes

  • The element and Detail name the field; correct the value and resend.

4000 — Query parse / validation error ​

HTTP 400 · QBO's own code for a query its grammar rejects. The Message starts with QueryParserError: (syntax) or QueryValidationError: (a property or value the entity doesn't accept), exactly as QBO words them.

Causes

  • Invalid syntax: a missing FROM, OR (the query language has none — join conditions with AND), an unquoted date or string, an unterminated string literal, parentheses around conditions, NOT LIKE, a bad STARTPOSITION / MAXRESULTS.
  • A property the entity doesn't have (property Foo not found in Customer), an operator a property doesn't take (LIKE on a number), or a literal of the wrong type (TxnDate >= 'yesterday').

Fixes

  • The Detail names the problem; correct the clause and resend.

2020 — Required parameter missing ​

HTTP 400/422 · A field the operation requires is missing — either one QBO requires, or one QuickBooks Desktop additionally requires (the Detail says which).

Fixes

  • Add the named field and resend. Desktop-only requirements are also flagged per entity on the compatibility page.

2050 — String length out of range ​

HTTP 400 · A string field is longer than QuickBooks Desktop allows. Raised by TenkeyBridge's own validation before the request reaches Desktop. Today this covers DocNumber (Desktop's RefNumber), counted in characters (Unicode code points):

  • 11 characters on Invoice, SalesReceipt, Estimate, CreditMemo, RefundReceipt, JournalEntry, PurchaseOrder, Purchase, and BillPayment.
  • 20 characters on Bill and VendorCredit.

It also covers Payment's PaymentRefNum, which maps to Desktop's RefNumber too and is limited to 20 characters. The element names the field (for example Invoice.DocNumber) and the Detail states the limit.

Causes

  • A DocNumber longer than the Desktop reference-number limit for that transaction type.

Fixes

  • Shorten the value and resend. QuickBooks Online allows longer document numbers than Desktop, so integrations moving from QBO should cap or truncate DocNumber up front.

500 — System failure ​

HTTP 500, SystemFault · TenkeyBridge hit an internal integrity error translating Desktop's response — for example a returned record missing its ListID or EditSequence. This is a TenkeyBridge bug, not a problem with your request.

Fixes

  • Retry once; if it persists, report it with the response's time field.

Desktop status codes ​

Any QuickBooks Desktop status code without a QBO mapping passes through untouched as the fault's code (message Business Validation Error), so no error is ever swallowed — and the raw QuickBooks message is always preserved in Detail, prefixed QuickBooks Desktop:. For the notoriously cryptic common ones, the tkb block explains what QuickBooks actually means:

Desktop codeWhat QuickBooks meansWhat to do
3000The record id is malformed for this entity — Desktop ListIDs/TxnIDs have entity-specific formats, so a QBO id or guessed value won't parse.Use an Id previously returned by TenkeyBridge for this entity.
3170The record could not be modified — commonly a value the QuickBooks UI would also refuse, or the record is held by another user or open window.Read the raw message in Detail; close the record's window in QuickBooks, or try single-user mode.
3175The record is locked by another QuickBooks user or an open window.Close the record's window; retry after the other session finishes.
3180General save error — frequent culprits are sales-tax configuration conflicts or lines referencing accounts/items that changed mid-save.Read the raw message in Detail; it usually names the list or field involved.
3250The feature the request needs is not enabled in this company file (inventory, sales tax, multicurrency, …).Enable the feature in QuickBooks preferences, or drop the fields that need it.
3260The QuickBooks user the agent session runs as lacks permission for this action.Grant the role the permission (Company → Set Up Users and Passwords), or run the agent session as a user with sufficient rights.
-1QuickBooks returned a response TenkeyBridge could not parse a status code from.Check the agent log on the host machine; report the fault with its Detail.

Mapped Desktop codes (3100→6240, 3120→610, 3200→5010, 3140→2500, 3070→2020) surface as their numeric QBO codes above.

Admin API errors ​

The Admin API (/admin/v1/*) speaks its own two-field { "error", "message" } shape too — not the QBO Fault shape above and not the OAuth shape below — see Admin API: Errors for the full table of general-purpose codes (unauthenticated, forbidden, not_found, …). The four codes below are billing-specific (#92); see the billing guide for the plan and grace-period rules behind them.

errorHTTPWhat happenedWhat to do
plan_limit_realms409POST /admin/v1/realms on a trial org that already has its one allowed realm connected. The body additionally carries checkoutPath, the org's checkout endpoint.Subscribe (POST the checkoutPath) to lift the one-realm trial limit, or delete/reuse the existing realm.
billing_disabled503POST .../billing/checkout or .../billing/portal-session called on a gateway with no Stripe configuration.Nothing to do as a caller — the gateway operator hasn't configured STRIPE_* secrets yet.
enterprise_plan409POST .../billing/checkout for an org already on the Enterprise plan.Enterprise is managed off-platform — contact sales@tenkeybridge.com, not Stripe Checkout.
no_customer409POST .../billing/portal-session for an org with no Stripe customer yet.Start checkout first (POST .../billing/checkout) — a Billing Portal session needs an existing Stripe customer to open.

OAuth errors ​

The OAuth endpoints (/oauth2/v1/*) speak RFC 6749, not the QBO Fault shape — errors come back as { "error", "error_description", "error_uri" }. error is the stable value to branch on; error_description says what actually went wrong.

errorHTTPWhat happenedWhat to do
invalid_client401Unknown client_id or wrong client_secret.Send HTTP Basic auth with client_id as username, client_secret as password.
invalid_grant (code exchange)400The authorization code is invalid, expired, already used, or was issued to a different client / redirect_uri.Codes are single-use, and the token request's redirect_uri must exactly match the authorize request's. Restart the connect flow for a fresh code.
invalid_grant (refresh)400The refresh token is invalid, expired, revoked, or already rotated.Every refresh returns a new refresh token — always store the latest. If the chain is lost, reconnect.
unsupported_grant_type400grant_type isn't one TenkeyBridge supports.Use authorization_code (first exchange) or refresh_token (renewal).
unsupported_response_type400/authorize called without response_type=code.TenkeyBridge implements the authorization-code flow only.
slow_down429Too many /authorize + /tokens requests from your IP in the last minute (shared budget across both).Wait for Retry-After seconds, then retry. Same RateLimit-* + Retry-After headers as RATE_LIMITED.

See the authentication guide for the full connect flow.

TenkeyBridge is an independent product, not affiliated with, endorsed by, or sponsored by Intuit Inc. QuickBooks, QuickBooks Online, and QuickBooks Desktop are trademarks of Intuit Inc., used only to describe compatibility.