Integrate the SDK

Errors

When something fails in a session — while it starts, while it runs, or when a request you made is rejected — it reaches your code as one typed error. You catch it, explain it to the user in your own words, and branch on it; every code it can carry is listed below.

The error object

Every error is one object:

Tip

Codes are stable — branch on error.code, never on the wording of error.message, which may change.

Categories and classes

Every error also belongs to a category, and each category has its own class. Catch the class to handle a whole family at once — SpeechineerQuotaError covers every way an allowance can run out — or read error.code when you need the specific cause:

CategoryClassWhen
clientSpeechineerClientErrorRaised by the SDK itself — nothing was sent. Fix locally; most are worth a retry button.
authSpeechineerAuthErrorA credential travelled and was refused. Fix the token or key configuration; do not retry unchanged.
quotaSpeechineerQuotaErrorAn allowance is spent. Surface it to the user or your operations; retrying will not help until limits change. error.meta carries the numbers — see below.
accessSpeechineerAccessErrorThe credentials are valid but this workspace, organization or account may not do it — nothing on the page side changes it.
not_foundSpeechineerNotFoundErrorSomething the request names does not exist. Check the key, version and language — retrying unchanged never helps.
goneSpeechineerSessionEndedErrorIt existed and has ended. Start a new one — this is the only category that can never be retried.
conflictSpeechineerConflictErrorThe request is well formed but disagrees with how the thing it names is already set up.
validationSpeechineerValidationErrorSpeechineer understood the request and refused its content. error.details lists one entry per offending field, and error.field names it when there is only one.
rate_limitSpeechineerRateLimitErrorNothing is spent — you are going faster than allowed. Retrying later is the fix.
runtimeSpeechineerRuntimeErrorThe session was live and could not continue. It is over — start a new one.
serviceSpeechineerServiceErrorOurs, not yours. Retrying later is reasonable; tell us the request id if it persists.
upstreamSpeechineerUpstreamErrorSomething Speechineer relies on replied with something unusable. Retrying later is reasonable.
unavailableSpeechineerUnavailableErrorNothing answered at all. Retrying later is reasonable.
timeoutSpeechineerTimeoutErrorThe work may or may not have happened. Retry only what is safe to repeat.

The numbers on a quota error

A quota error is the one category that carries figures, on error.meta. The keys are the same whether the allowance ran out on the request that started the session or while it was running, so one piece of code renders both:

KeyWhat it holds
limitThe ceiling that bound, in units.
usedHow much of it was already consumed.
remainingWhat was left — 0 whenever the error fired.
layerWhich allowance bound, as `<scope>:<period>` — e.g. `account:month`. This is what tells a spent account apart from a spent workspace.

Listen for errors

However a session fails, you never have to hunt for the error: the same object is delivered to three places, each suited to a different job — a callback for reacting the moment something fails, the session state for rendering, and the rejected promise for the code that asked. Use whichever fits the code you are writing.

  • The onError callback — called the moment it happens. Log the error or send it to analytics from there:
    ts
    const voice = useSpeechToForm({
      form: intakeForm,
      onError: (error) => showBanner(error.code),
    });
  • The session state — the error sits there as error and stays until the next start() succeeds. Render your message from there — describe is your own mapping from a code to your wording:
    tsx
    {voice.error && <p role="alert">{describe(voice.error.code)}</p>}
  • The rejected promise — start() and end() reject with the same error, so an await where you call them catches it directly:
    tsx
    const onSpeak = async () => {
      try {
        await voice.start();
      } catch (error) {
        showBanner(error.code);
      }
    };

Error codes

One section per category, so a section is exactly what one catch gives you: the class in the heading is what instanceof matches, and the codes under it are every way that class can arrive. The codes are frozen — they will not change under you.

In the browser

SpeechineerClientError · client — Raised by the SDK itself — nothing was sent. Fix locally; most are worth a retry button.

CodeMeaningPossible fix
MICROPHONE_DENIEDMicrophone access was blocked, or the page is not on a secure origin (HTTPS or localhost). Worth asking again.Serve over HTTPS or localhost and surface the browser's permission prompt again — offer a retry button.
MICROPHONE_UNAVAILABLENo usable microphone was found.Ask the user to plug in or enable a microphone, then retry; check the browser's device permissions.
AUDIO_UNSUPPORTEDThis browser cannot record audio in the required format.Ask the user to switch to a current browser; no configuration on your side changes this.
NETWORKThe request never got an answer — connectivity, or the browser blocked the request (check its console).If the browser console shows a blocked cross-origin request, your origin was refused — check baseUrl for typos and tell us the origin you serve from. Otherwise check connectivity and retry.
NO_SESSIONAn action was called before start().Call start() before stop(), end() or any other action, or guard the action on the session's state.
NO_CLIENTNo client is provided above this component — the provider / provide call is missing.Wrap the component in the provider (React), call the provide function at bootstrap (Angular), or pass the client explicitly.
NO_AUTHThe SDK had no credentials to send — nothing reached Speechineer. Distinct from AUTH_REQUIRED, which means a credential was sent and refused.Pass the API key to createClient — or, in Signed mode, make sure your token endpoint returns a token.
NO_ACCOUNTAn account is required alongside an API key, and none was given.Pass account to createClient, or to the session when it differs per user.
UNKNOWNSomething failed in a way the SDK could not name — the last resort, not a category.Read error.cause for what actually threw, and tell us the request id if one is set.

Authentication

SpeechineerAuthError · auth — A credential travelled and was refused. Fix the token or key configuration; do not retry unchanged.

CodeMeaningPossible fix
AUTH_REQUIREDA credential was presented and Speechineer refused it — missing, malformed or expired.Check the token has not expired and is minted for the right workspace; re-mint and retry once.
API_KEY_INVALIDThe API key in the token is unknown or inactive.Check the key against API keys in your workspace; create a new one if it was deactivated or archived.
AUTH_SIGNATURE_REQUIREDThe workspace or key requires a PS256-signed token; alg=none was presented.This page needs a Signed key: mint PS256 tokens in your backend with a signing key, or use an Unsigned key only where the workspace allows it.
AUTH_MODE_MISMATCHThe token's alg does not match the API key's auth mode (Signed keys accept only PS256; Unsigned keys only alg=none).Check which client the page resolves and which mode its key carries — one app can hold both (see Authentication).
AUTH_ENVELOPE_INVALIDThe token is malformed, or its claims are missing or wrong.Compare the claims your backend signs with the reference set (api_key, account_key, aud, iat, exp, jti) and the alg / kid header.
AUTH_ENVELOPE_REPLAYEDThis token was already used (replayed `jti`).Mint a fresh token per session start with a unique jti; never cache a token across sessions.
AUTH_ENVELOPE_LIFETIME_EXCEEDEDThe token is valid for longer than the maximum allowed lifetime.Shorten exp − iat in your backend; a few minutes is plenty, the SDK asks for a new token every start.
ACCOUNT_REQUIREDThe token does not name an account.Add the account claim to the token (Signed) or pass account.key to createClient (Unsigned).
SIGNING_KEY_NOT_FOUNDThe token's key id matches no active signing key in the workspace.Put the signing key's id in the token's kid header, and check the key is still active in Signing keys.

Quotas and billing

SpeechineerQuotaError · quota — An allowance is spent. Surface it to the user or your operations; retrying will not help until limits change. error.meta carries the numbers — see below.

CodeMeaningPossible fix
API_KEY_QUOTA_EXCEEDEDThe API key's units limit is reached.Raise or remove the key's units limit in its settings, or wait for the period to roll over.
WORKSPACE_QUOTA_EXCEEDEDThe workspace units limit is reached.Raise the workspace limit in its settings, or wait for the period to roll over.
ACCOUNT_QUOTA_EXCEEDEDThe account's units limit is reached.Raise the account's limit from your backend or in Accounts; tell the user their allowance is used up.
FORM_QUOTA_EXCEEDEDThe form's units limit is reached.Raise the form's units limit in its settings, or wait for the period to roll over.
PLAN_ALLOWANCE_EXHAUSTEDIncluded units are used up and no prepaid units remain.Buy prepaid units or wait for the next cycle; the dashboard shows what remains.
OVERSPEND_LIMIT_REACHEDThe configured overspend cap is reached.Raise the overspend cap in Billing, or wait for the next cycle.
QUOTA_EXCEEDEDAn allowance ran out while the session was running, so the session ended there. Which allowance it was is in error.meta.layer.Raise the limit that bound, then start a new session; the one that ended cannot be resumed.

Not allowed

SpeechineerAccessError · access — The credentials are valid but this workspace, organization or account may not do it — nothing on the page side changes it.

CodeMeaningPossible fix
WORKSPACE_INACTIVEThe workspace is deactivated or archived.Reactivate the workspace in its settings; an archived workspace cannot be brought back — create a new one.
CLIENT_INACTIVEThe owning organization is deactivated.Contact your organization's owner; nothing on the page side fixes this.
ACCOUNT_INACTIVEThe end user's account is deactivated or archived.Reactivate the account in Accounts, or point the session at a different one — an archived account is final.
FEATURE_NOT_AVAILABLEThe plan does not include the capability this session asked for.Check what your plan covers in Billing; ask us to enable the capability if you need it.

Named but not there

SpeechineerNotFoundError · not_found — Something the request names does not exist. Check the key, version and language — retrying unchanged never helps.

CodeMeaningPossible fix
FORM_NOT_FOUNDNo form with this key in the workspace.Compare form.key with the key shown on the form's page; a key belongs to one workspace only.
FORM_VERSION_NOT_PUBLISHEDThe version your code names exists but is a draft.Publish it from the form's header (Publish this version), or point version at the published one.
NO_PUBLISHED_VERSION_FOR_LANGUAGENo published version exists for the requested language.Add the language to the form and publish, or request a language the published version supports.
WORKFLOW_NOT_FOUNDThe requested workflow does not exist.Check the workflow name; leave it unset to get the default.
NOT_FOUNDSomething the request names does not exist, where no more specific code fits.Check every key the call passes against what your workspace holds.
WORKFLOW_FEATURE_UNKNOWNThe workflow does not offer the capability the session asked for.Check which capability you start against what the workflow supports.
ADAPTER_CONFIG_NOT_FOUNDA model this session pins by name is not registered for your workspace.Check the model keys you pass; leave them unset to use the ones the form already names.
SESSION_NOT_FOUNDThe workflow you tried to resume no longer exists.Start a new session instead of resuming; the previous one has expired.

The session is over

SpeechineerSessionEndedError · gone — It existed and has ended. Start a new one — this is the only category that can never be retried.

CodeMeaningPossible fix
SESSION_ENDEDThe session existed and is over — every call against it answers this from then on. What ended it is the first entry of error.details, so a spent allowance still reads as one.Start a new session; this one cannot be resumed. If what ended it was a quota, raise the limit first.

Conflicts with what exists

SpeechineerConflictError · conflict — The request is well formed but disagrees with how the thing it names is already set up.

CodeMeaningPossible fix
FORM_KEY_PORTAL_OWNEDThis form is configured in Speechineer — use source: "workspace" for it.Name the form with source: "workspace" instead of passing an inline definition under that key.
COMPONENT_IN_USEThe thing you tried to remove is still referenced by something live.Detach or archive what still points at it, then retry.

The request was not acceptable

SpeechineerValidationError · validation — Speechineer understood the request and refused its content. error.details lists one entry per offending field, and error.field names it when there is only one.

CodeMeaningPossible fix
VALIDATION_ERROROne or more fields of the request are missing or out of range.Read error.details — each entry names the field and what was wrong with it.
FORM_FIELD_INVALIDA field in an inline form definition is not valid for its type.Check the field's type against what it carries — a slider needs a range, a select needs options.
CONFIG_INVALIDThis workflow's configuration is incomplete or invalid.Check the model keys and prompts the session pins; an inline form must supply everything the models it selects require.
WORKFLOW_STANDALONE_MODE_UNSUPPORTEDThis workflow has no standalone mode.Use a workspace form for this workflow; inline definitions are not supported here.
ADAPTER_CONFIG_NOT_ALLOWEDA model was pinned for a capability this workflow does not have.Pin models only for the capabilities the workflow actually runs.
ADAPTER_CONFIG_NOT_ENTITLEDYour plan does not include the model this session pins.Choose a model your plan covers, or ask us to enable it.
FORM_VERSION_LANGUAGE_UNAVAILABLEThe published version does not carry the language the session asked for.Add the language to the form and publish it, or ask for one the version already has.
FEATURE_CONFIG_INVALIDThe capability's configuration is not valid for this form.Read error.details — each entry names the setting and what was wrong with it.
FEATURE_FIELD_CONFIG_REQUIREDA field is configured in code but the call did not supply its configuration.Pass fieldConfigs for every field the form leaves open for code.
FEATURE_SETTING_NOT_ALLOWEDA setting the call passes may not be set from code for this form.Drop the setting — the form's configuration owns it.
FEATURE_SETTING_INVALIDA setting the call passes is outside the values it accepts.Read error.details for the accepted range, and pass a value inside it.
WEBSOCKET_KIND_UNSUPPORTEDA connection was opened that this session does not use. The session keeps running; only that connection was refused.Open only the connections the capability you started uses — the session answer lists them.

Too much at once

SpeechineerRateLimitError · rate_limit — Nothing is spent — you are going faster than allowed. Retrying later is the fix.

CodeMeaningPossible fix
CONCURRENCY_LIMIT_REACHEDToo many workflows are running concurrently.End sessions you no longer need, queue starts on your side, or ask for a higher concurrency limit.

A running session stopped

SpeechineerRuntimeError · runtime — The session was live and could not continue. It is over — start a new one.

CodeMeaningPossible fix
TRANSCRIPTION_FAILEDTranscription stopped and could not be restarted.Start a new session. If it recurs on one form, try its prompts in the Engineer tab.
EXTRACTION_FAILEDField extraction stopped and could not be restarted.Start a new session. If it recurs on one form, try its prompts in the Engineer tab.

Speechineer could not answer

SpeechineerServiceError · service — Ours, not yours. Retrying later is reasonable; tell us the request id if it persists.

CodeMeaningPossible fix
INTERNAL_ERRORSomething failed on our side that we did not anticipate.Retry once; if it persists, send us error.requestId.

A dependency answered badly

SpeechineerUpstreamError · upstream — Something Speechineer relies on replied with something unusable. Retrying later is reasonable.

CodeMeaningPossible fix
UPSTREAM_INVALIDA service Speechineer depends on returned an answer it could not use.Retry; if it persists, send us error.requestId.

A dependency could not be reached

SpeechineerUnavailableError · unavailable — Nothing answered at all. Retrying later is reasonable.

CodeMeaningPossible fix
SERVICE_UNAVAILABLEA service Speechineer depends on could not be reached.Retry with a short backoff; if it persists, send us error.requestId.

A dependency took too long

SpeechineerTimeoutError · timeout — The work may or may not have happened. Retry only what is safe to repeat.

CodeMeaningPossible fix
ACTION_TIMEOUTAn action did not complete within the time allowed for it.Retry the action; if it times out repeatedly, send us error.requestId.