koala73/worldmonitor · error
Sign in to revoke embed keys.
Error message
Sign in to revoke embed keys.
What it means
revokeEmbedKey(keyId) requires an authenticated user: it reads the current Clerk user id, and if there is none it throws this error before any Convex call. Unlike the read path (listEmbedKeys returns []), a destructive mutation refuses to silently no-op when signed out.
Solutions
- Check getCurrentClerkUser() for a non-null user before offering/invoking revocation, and route to sign-in instead
- Sign in with Clerk, then retry the revocation
- If the session just expired, refresh the page so Clerk rehydrates before retrying
Example fix
// before
await revokeEmbedKey(keyId);
// after
if (!getCurrentClerkUser()) {
openSignIn();
return;
}
await revokeEmbedKey(keyId); Defensive patterns
Strategy: validation
Validate before calling
if (!getCurrentClerkUser()) { openSignIn(); return; } Type guard
const isSignedIn = (): boolean => getCurrentClerkUser() != null;
Prevention
- Disable destructive actions until a Clerk user exists
- Route to sign-in instead of calling the API when signed out
- Treat session expiry proactively in long-lived tabs
When it happens
Trigger: Calling revokeEmbedKey(keyId) when getCurrentClerkUser() returns undefined — i.e. the visitor is signed out, or the Clerk session has been lost/expired at the moment of the call.
Common situations: Clicking 'revoke' on an embed key after the Clerk session expired in a long-lived tab; calling the API from code that runs before Clerk finishes initializing; a signed-out state after session revocation on another device.
Related errors
- UNAUTHENTICATED
- Authentication unavailable while loading MCP clients. Try ag
- Sign in to revoke MCP clients.
- Not authenticated
- Authentication unavailable while loading Business Pro seats.
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/09b0375467cbc885.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/embed-keys.ts:141
() => client.query((api as any).embedKeys.listEmbedKeys, {}),
);
}
/**
* Revoke an embed key by its Convex document ID.
*
* Unlike `revokeApiKey`, this does not bust the edge validation cache: there is
* no ownership-checked invalidation route for `embedKeys` yet, so a revoked key
* keeps validating for at most the 60s `CACHE_TTL_SECONDS` in
* `server/_shared/embed-key.ts`.
*
* A map frame is slower still: it already holds a `wmg_` grant good for up to
* `EMBED_GRANT_TTL_MS` (30 minutes), and revocation only stops the NEXT mint.
* The UI copy states both windows rather than promising one.
*/
export async function revokeEmbedKey(keyId: string): Promise<void> {
const userId = getCurrentClerkUser()?.id;
if (!userId) throw new Error('Sign in to revoke embed keys.');
const [client, api] = await Promise.all([getConvexClient(), getConvexApi()]);
if (!client || !api) throw new Error('Convex unavailable');
if (!await waitForConvexAuthForUser(userId)) {
throw new Error('Account changed while revoking the embed key. Try again.');
}
await settleAccountOperation(
userId,
'revoking the embed key',
() => client.mutation((api as any).embedKeys.revokeEmbedKey, { keyId }),
);
assertAccountStillCurrent(userId, 'revoking the embed key');
}
View on GitHub (pinned to 7d06c8633d)