The BI endpoints carry their own code vocabulary on top of the shared one. Every code below
resolves here, which is why a BI error’s docs_url points at this page rather than a per-code
one — only not_found and internal_error are shared with the rest of the API and have pages of
their own.
Every BI error uses the structured envelope, on every response, regardless of the Accept header
you send:
{
"error": {
"code": "feature_disabled",
"message": "SQL console is not enabled for this organization",
A query submission supplied both sql and definition, or neither.
Send exactly one query form.
invalid_definition
400
A structured definition is malformed or names something outside the authorized catalog.
Rediscover the schema, then rebuild the definition from returned names and supported operators.
invalid_sql
400
sql is missing, not a string, or over 100,000 characters.
Send a non-empty string within the limit.
syntax_error
400
The engine rejected your SQL. The message carries the engine’s own parse detail, including position — this is the one place raw engine text is passed through, because it describes SQL you wrote.
Fix the statement and resubmit.
invalid_label
400
label is not a string, or over 200 characters.
Shorten it or omit it.
invalid_idempotency_key
400
Idempotency-Key is present but is not a UUID.
Generate one UUID per intended query run and reuse it only when retrying that run.
invalid_submission_key
400
The query-history submissionKey filter is not a UUID.
Use the UUID sent as the original query’s Idempotency-Key to recover its retained handle.
invalid_execution_context
400
sourceQueryId is malformed or was supplied without a SQL edit, or a request tried to provide server-owned scope/dialect fields.
Send an owned query UUID only alongside edited sql; never send scope or dialect fields.
invalid_table_name
400
The table name in the path is not a valid identifier.
Use a name exactly as returned by GET /api/v1/bi/schema.
statement_timeout
504
The query exceeded the time limit. The limit that applied is reported as maxQuerySec by the result manifest.
Narrow the range, add a WHERE, or aggregate server-side.
No such query, export, or saved query in your organization. Not-yours and not-exists are deliberately indistinguishable so cross-tenant ids cannot be probed.
Check the id and the org the token belongs to.
not_ready
409
The query has not reached success yet. The body carries the current status as a sibling of error.
Poll GET /api/v1/bi/queries/{id} until it is terminal.
idempotency_conflict
409
This organization already used the supplied Idempotency-Key for a different user, SQL, label, source query, or agent scope.
Do not retry with that key. Generate a new UUID for a genuinely new run, or resend the original request unchanged.
too_many_queries
429
Your organization’s concurrency or queue-depth cap is full.
No Retry-After header is sent — back off with capped exponential retry.
canceled
409
The query was canceled before it finished.
Resubmit if you still want the result.
transient
409
An engine or network blip unrelated to your SQL.
Retry; this one is expected to succeed on a second attempt.
name is missing, not a string, or over 120 characters.
Send a non-empty name within the limit.
invalid_description
400
description is not a string or null, or is over 1,000 characters.
Send a string, or null to clear it.
invalid_body
400
A PATCH arrived with no updatable field.
Include at least one of name, sql, description, chartConfig.
invalid_saved_query_input
400
Saved-query creation supplied both sql and sourceQueryId, or neither.
Send exactly one source form.
invalid_source_query
400
sourceQueryId is not a UUID.
Send the id of a completed query in your organization.
invalid_cursor
400
The saved-query list cursor is malformed or no longer decodes to a valid position.
Restart pagination without a cursor.
invalid_chart_config
422
chartConfig is present but malformed. 422 rather than 400 so a broken chart payload is distinguishable from a missing name or sql.
Send {type, x, y} where type is bar, line, or pie; pie takes a single y.
saved_query_name_taken
409
Another saved query in your org already has that name.
Pick a different name.
source_query_not_executable
409
The source query is not complete or has no valid immutable execution scope.
Wait for completion and save that run; legacy unknown-scope rows cannot be promoted.
saved_query_not_executable
409
The saved object has no executable content with a proven immutable scope.
Recreate it from a completed query or contact support if it predates scoped saves.
not_structured
409
SQL conversion was requested for a saved query that is already editable SQL.
Edit the existing SQL directly.
conversion_unavailable
409
The stored definition no longer resolves against the current authorized catalog.
Rediscover the schema and rerun or recreate the structured query.
has_active_schedules
409
The saved query has enabled schedules attached, which block deletion. The blocking names are in error.schedules — inside the error object, not beside it. Disabled schedules do not block and are removed along with the query.
Disable or delete the named schedules, then retry.
These are not HTTP errors. An export that cannot be delivered ends with status: "failed", and
GET /api/v1/bi/exports/{exportId} returns one of these codes in errorCode, with customer-safe
text in errorMessage. The response keeps both the export id and its source query id.
errorCode
What it means
What to do
source_unavailable
The source query’s stored results no longer exist, for example after they expire.
Re-run the source query, then export the new run.
source_malformed
The source query’s stored results are incomplete or could not be read back.
Re-run the source query and export the new run. Contact support with the export id if it recurs.
source_too_large
The stored result is larger than the export size limit, which is checked while the file is built.
Narrow the query with LIMIT, WHERE, or fewer columns, re-run it, then export.
source_read_failed
Reading the stored results failed for a reason unrelated to your query.
Request the export again.
upload_failed
Writing the finished file to storage failed. Uploads are retried automatically before an export fails.
Request the export again.
encoding_error
The rows could not be encoded as CSV or Parquet.
Try the other format, or cast unusual column types to text in the query and re-run it.
retry_exhausted
Every attempt failed on a temporary error, and the export ran out of retries.
Request a new export later. Contact support with the export id if it keeps happening.