dubinc/dub · error
Access token not found for the account.
Error message
Access token not found for the account.
What it means
getValidToken loads the stored Dub token from Stripe app secrets (name "dub_token"); when no secret exists it throws this message. It means the account never completed (or its data was lost from) the Dub connect flow, so no token is available to validate or refresh.
Source
Thrown at packages/stripe-app/src/utils/oauth.ts:98
throw new Error("Failed to fetch user info from Dub.", {
cause: data.error,
});
}
const { workspace } = data as { workspace: Workspace };
return workspace;
}
// If the token is expired, it will refresh it
export async function getValidToken({ stripe }: { stripe: Stripe }) {
const token = await getSecret<Token>({
stripe,
name: "dub_token",
});
if (!token) {
throw new Error("Access token not found for the account.");
}
try {
await getUserInfo({ token });
} catch (e) {
const refreshedToken = await refreshToken({ token });
if (!refreshedToken) {
console.error("Failed to refresh access token.");
return null;
}
await setSecret({
stripe,
name: "dub_token",
payload: JSON.stringify(refreshedToken),
});
View on GitHub (pinned to f216b94a24)
Solutions
- Complete the Dub connect/OAuth flow in the Stripe App so dub_token is stored as a secret.
- Verify you are operating on the same Stripe account that performed the connection.
- Reinstall/re-authorize the Stripe App if secrets were wiped.
- Add a UX guard: check for the token first and show 'Connect Dub' instead of a raw error.
Example fix
// before
const token = await getValidToken(stripe); // throws for unconnected accounts
// after
const stored = await getSecret({ stripe, name: "dub_token" });
if (!stored) return showConnectOnboarding(); Defensive patterns
Strategy: validation
Validate before calling
const stored = await getSecret<Token>({ stripe, name: "dub_token" });
if (!stored) {
// render onboarding instead of calling Dub-dependent handlers
return respondWith({ connectUrl: buildDubConnectUrl(stripeAccountId) });
} Type guard
function isStoredToken(v: unknown): v is { access_token: string; refresh_token: string } {
return typeof v === "object" && v !== null && typeof (v as any).access_token === "string" && typeof (v as any).refresh_token === "string";
} Try / catch
try {
const token = await getValidToken({ stripe });
} catch (e) {
if ((e as Error).message === "Access token not found for the account.") {
return startDubOnboarding(stripeAccountId); // friendly connect flow
}
throw e;
} Prevention
- Gate all Dub features behind a 'connected?' check that reads the secret first.
- Persist dub_token during install; block feature use until the OAuth flow completes.
- Handle account switching — secrets are per Stripe account.
- Warn users on reinstall that reconnection is required.
When it happens
Trigger: A Stripe App request path calls getValidToken (via the `token` handler) for an account where getSecret returns null — the user installed the app but never authorized Dub, or the secret was deleted.
Common situations: Stripe App installed but OAuth connect step skipped; secrets cleared by reinstall; calling Dub-backed features from a different Stripe account than the one that connected.
Related errors
- data.error.message
- Failed to fetch user info from Dub.
- Access token not found. Please run `dub login` to authentica
- Failed to update workspace.
- Not found
AI-assisted analysis of dubinc/dub@f216b94a24 (2026-08-31).
Data as JSON: /api/errors/245991eecc07af93.
Report an issue: GitHub.