Handle NotConnected
Surface a structured needs_connection payload so the frontend can redirect users to the connect portal.
NotConnected is raised by vendo.data.execute when the provider required by the action is not connected (binding_missing from the proxy). The correct response is to return a structured payload so the frontend can redirect the user to the connect portal.
STRIPE_LIST_CUSTOMERSin the example below is the Composio action id pattern —<TOOLKIT>_<ACTION>in SCREAMING_SNAKE_CASE. Confirm the exact spelling against composio.dev before shipping; the proxy is a pass-through and Vendo doesn't curate the action catalog.
connections.get(slug) returns None / null (not NotConnected) when the provider is not connected. These are two different signals for two different code paths — see the comparison table below.
Catch NotConnected from data.execute
import vendo
from vendo.errors import NotConnected
def run_stripe_action(client):
try:
return {"customers": client.data.execute("STRIPE_LIST_CUSTOMERS", {"limit": 10})}
except NotConnected as e:
# e.slug is the missing provider, "stripe" here.
slug = e.slug or "stripe"
return {
"needs_connection": slug,
"connect_url": vendo.connect_url(slug),
}import { Vendo, NotConnected } from "@vendodev/sdk";
const vendo = new Vendo();
async function runStripeAction() {
try {
return { customers: await vendo.data.execute("STRIPE_LIST_CUSTOMERS", { limit: 10 }) };
} catch (e) {
if (e instanceof NotConnected) {
const slug = e.slug ?? "stripe";
return {
needsConnection: slug,
connectUrl: vendo.connectUrl(slug),
};
}
throw e;
}
}Handle the response on the frontend
The frontend receives { needs_connection: "stripe", connect_url: "..." } and opens the connect portal:
const res = await fetch("/api/stripe-customers");
const data = await res.json();
if (data.needs_connection) {
// Open the Vendo connect portal in a popup
window.open(data.connect_url, "vendo-connect", "width=500,height=700");
}After the user connects, the portal closes and Vendo emits a connection.connected event on the SDK's SSE stream. Subscribe with vendo.events.subscribe() (or client.events.subscribe() on an instance) and call vendo.invalidate(slug) when you see the event — the next data.execute call then picks up the fresh binding without a process restart.
connections.get vs NotConnected — which to use
| Situation | Pattern |
|---|---|
| Check if a provider is connected before doing anything | connections.get(slug) returns None |
| Execute an action and handle failure if not connected | data.execute raises NotConnected |
| Show a connect button in the UI before the user attempts an action | connections.get(slug) — render the setup_url from the returned entry |
| Execute an action and want a single try/catch for all error cases | Catch NotConnected from data.execute |
NotConnected error fields
| Field | Type | Description |
|---|---|---|
slug | str | None | The provider slug that is not connected, e.g. "stripe". Optional — fall back to a known slug if absent. |
connect_url | str | None | Pre-computed connect URL, when the proxy was able to build one. |
message | str | Human-readable message. |
Notes
- In Vendo mode
connect_urlreturns a working URL only whenVENDO_API_KEYis set. Do not call it in OSS mode. - The
setup_urlfield on aConnectionentry returned byconnections.list()is the same URL — use it when you want to pre-render the connect button without waiting for aNotConnectederror. - After the user connects, the next call to
connections.get(slug)returns the connection, anddata.executesucceeds. You do not need to restart the process.