Skip to content

Ask AI

Ask anything about Destesi — setup, products, APIs.

Powered by Claude. Answers may be wrong — always verify against the docs.

Troubleshooting

Real failure modes and how to fix them.

Open connect.destesi.io, pick a connection, and the detail page shows an Actions panel. Which buttons appear depends on the connection’s status and provider:

  • Re-validate — always shown. Pings the provider with the stored credential and refreshes the connection’s status and Last validated time. Use this whenever a status looks stale or a product reported a problem you think was transient.
  • Reconnect — shown when the connection is not ACTIVE and uses OAuth. Re-runs the provider’s consent flow and lands you back on the detail page. For API-key providers (an AI provider, a stock provider, Wompi, Skydropx, and the like) this same slot reads Rotate API key and opens the key entry form instead — pasting a fresh key overwrites the stored one in place (you don’t disconnect first).
  • Set as default — shown only for multi-account providers when this connection isn’t already the default. Products that don’t name a specific account use the default.
  • Disconnect — always shown. Removes the connection after a confirmation prompt; you can reconnect anytime.

A product says “reconnect” or a connection shows EXPIRED

Section titled “A product says “reconnect” or a connection shows EXPIRED”

OAuth tokens expire. Connect refreshes them automatically when a product fetches the credential, but if the refresh itself fails — usually because you revoked Destesi’s access on the provider’s side, or the provider invalidated the grant — the connection flips to EXPIRED and products can no longer use it.

Fix: open connect.destesi.io, find the connection, and reconnect it (run the OAuth flow again). One reconnect in Connect restores it for every product in the workspace.

ERROR means a product tried to use the credential and the provider rejected it — for example a publish hit a quota or the account lost a required permission. The credential may still be valid for other operations.

Fix: open the connection’s detail page and click Re-validate (this pings the provider and refreshes the status). If it comes back ACTIVE, the error was transient. If it stays unhealthy, Disconnect and reconnect to re-grant scopes.

An API key is rejected when I try to save it

Section titled “An API key is rejected when I try to save it”

When you paste a key for an API-key provider (Pexels, ElevenLabs), Connect validates it against the provider before saving. A rejection returns invalid_api_key (HTTP 422) and nothing is stored.

Checklist:

  • Copy the key exactly — no surrounding whitespace, no truncation.
  • Confirm the key is for the right provider and account, and is still active in the provider’s dashboard.
  • Check the key has the access the validation call needs (Connect verifies it with a lightweight authenticated request to the provider).

To replace a key on a connection that already exists, open its detail page and click Rotate API key — the new key overwrites the stored one in place once it validates.

The tile tells you which case you’re in:

  • The tile shows as not configured. OAuth providers only become connectable once their application credentials are set in the deployment. If you self-host, set the provider’s credentials — usually a CONNECT_TPA_<PROVIDER>_CLIENT_ID / ..._CLIENT_SECRET pair, though several providers need an extra value (see the Reference). The catalog reports configured: false for any provider still missing credentials, and connect-api logs the dormant ones at startup.
  • The tile gives a reason for being unavailable. The connector normally works but is temporarily unavailable — the reason is shown rather than hidden, so you know to try again later.

The OAuth flow redirects to an unexpected page (or back to the catalog)

Section titled “The OAuth flow redirects to an unexpected page (or back to the catalog)”

After approving the provider’s consent screen, Connect redirects you to a return destination. A return URL is only honored when its origin is on the configured allowlist; an unrecognized origin is silently treated as “no return URL” and you land back on your connections page rather than the flow erroring out.

If you self-host: make sure the origin you expect to return to is listed in CONNECT_WEB_URL_ALLOWLIST, and that CONNECT_OAUTH_REDIRECT_BASE_URL matches the redirect URL registered in the provider’s OAuth app (the callback path is /v1/connections/callback?provider=<id>). A mismatch here is the most common cause of a failed OAuth round-trip.

Multi-account: the picker is empty or I picked the wrong accounts

Section titled “Multi-account: the picker is empty or I picked the wrong accounts”

After the consent screen for a multi-account social provider, Connect lists the accounts that grant exposes so you can choose which to add.

  • Empty picker: the connected provider account doesn’t manage any downstream accounts of the needed type (for example a Google login with no YouTube channels, or a Meta login with no Instagram business accounts). Connect the right upstream account, or create the downstream account on the provider first.
  • Wrong selection: Disconnect the unwanted connections from the Connect UI and re-run the flow. You can also change which account is the default with Set as default on the connection you want — products that don’t name a specific account use the default.

A server-side credential fetch returns 401 or 404

Section titled “A server-side credential fetch returns 401 or 404”

These come from the controller API:

  • 401 — either the server’s controller secret is unset (so the credential, connections, and mark-error routes reject everything) or the Authorization: Bearer <secret> you sent doesn’t match it. Confirm IDENTITY_CONTROLLER_SECRET is set on the connect-api side and that you’re sending the same value as the bearer.
  • 404 — from the credential route, this means the workspace simply has no connection for that provider. Confirm the workspace actually connected it.

Actions return a small, closed set of codes — see the full table. The ones you’ll actually hit:

  • not_connected (409) — the workspace has no connection for that provider. Connect it, then retry.
  • insufficient_scope (403) — the connection works but wasn’t granted a permission the action needs. Disconnect and reconnect to re-grant scopes; approving the consent screen again is what widens them.
  • invalid_args (422) — an argument failed the action’s schema, or you sent one the action doesn’t declare. Undeclared arguments are rejected rather than quietly forwarded, so check the action’s schema in the catalog.
  • missing_workspace (400) — you sent a token without naming a workspace. Add X-Destesi-Workspace: <slug> (or ?ws=<slug>).
  • A non-ok result with the provider’s own status — that isn’t an error from Connect, it means the provider answered and declined. The upstream status is in the result, which is how you tell “we couldn’t reach them” apart from “they said no”.

Work down the chain — the failure is almost always at one specific link:

  • Nothing arrives at all. The provider isn’t posting to the ingest URL. Remember Connect does not register the webhook for you: paste the ingest URL into the provider’s own webhook settings.
  • Deliveries are rejected on arrival. The signature didn’t verify against the subscription’s inbound secret. Re-paste the secret at the provider; if you no longer have it, the reveal is one-time and cannot be repeated — create a new subscription.
  • The subscription is paused, or the event doesn’t match. Both are acknowledged and dropped on purpose, so the provider sees success while nothing is forwarded. Check the status and the event type.
  • Deliveries are recorded but failing. Your endpoint returned something other than 2xx. Open the deliveries list to see the attempts; Connect retries with growing backoff before marking one failed.
  • unsafe_target (422) when creating. The endpoint isn’t reachable under the delivery guard — it must be HTTPS on a public address. A private, loopback, or link-local address is refused by design.
  • The same event arrives twice. Expected. Delivery is at-least-once; dedupe on delivery_id.

Some capabilities switch off cleanly when their dependency isn’t configured, rather than half-working:

  • chat_disabled (503) — Connect’s agent has no model configured. The rest of Connect is unaffected.
  • persistence_disabled (503) — chat history has no database; conversations still stream but aren’t saved.
  • github_installs_disabled (503) — the GitHub App installations page isn’t wired up in this deployment.
  • already_revealed (410) — trigger secrets were already revealed once. They cannot be shown again.

Stock search resolves an API key per provider, preferring the workspace’s stored connection and falling back to a process-wide default key. If neither exists for a provider, that provider is skipped.

Fix: connect a stock provider in Connect, or (when self-hosting) set the fallback key for the provider you want searched — UNSPLASH_ACCESS_KEY, PEXELS_API_KEY, or PIXABAY_API_KEY. Remember per_page is capped at 30.

  • Check the connection’s status and last error in the Connect UI — both are surfaced per connection.
  • Click Re-validate on the connection to get a fresh status straight from the provider.
  • For self-hosted deployments, the startup log lists which providers are configured and which are dormant; GET /readyz reports dependency health.