koala73/worldmonitor · error
Convex unavailable
Error message
Convex unavailable
What it means
createEmbedKey needs both a Convex client and the generated Convex API reference; Promise.all resolves both and if either is null/undefined (Convex not configured or client initialization failed) this error is thrown. It signals the app's persistence backend is unavailable, not an auth or input problem.
Solutions
- Verify the Convex URL environment variable is set in the deployment/localhost env and restart.
- Ensure the ConvexProvider is mounted at the app root so getConvexClient() can resolve.
- Run `convex dev` / redeploy the Convex functions and confirm the generated api reference matches.
- Add a startup check that surfaces a clear configuration error if Convex is unset.
Example fix
// before
const [client, api] = await Promise.all([getConvexClient(), getConvexApi()]);
if (!client || !api) throw new Error('Convex unavailable');
// after
const convexUrl = import.meta.env.VITE_CONVEX_URL;
if (!convexUrl) throw new Error('VITE_CONVEX_URL is not configured');
const [client, api] = await Promise.all([getConvexClient(), getConvexApi()]);
if (!client || !api) throw new Error('Convex unavailable — check provider mounting'); Defensive patterns
Strategy: validation
Validate before calling
if (!import.meta.env.VITE_CONVEX_URL) throw new Error('Convex URL env var is not set');
const client = getConvexClient();
if (!client) throw new Error('ConvexProvider not mounted'); Type guard
const convexReady = (): boolean => getConvexClient() != null && getConvexApi() != null;
Try / catch
try {
await createEmbedKey(name);
} catch (e) {
if (e.message === 'Convex unavailable') {
showError('Backend not configured — check the Convex deployment URL.');
} else throw e;
} Prevention
- Assert required Convex env vars at boot with a clear failure message.
- Mount ConvexProvider at the app root in every entry point.
- Smoke-test Convex connectivity on app startup.
When it happens
Trigger: getConvexClient() or getConvexApi() returns null — e.g. NEXT_PUBLIC/VITE Convex URL env var missing, ConvexProvider not mounted, or client construction failed during boot.
Common situations: Deploying without the Convex deployment URL environment variable set; running locally without `convex dev`; a build that tree-shook or misconfigured the Convex provider; Convex deployment deleted or renamed.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- EMBED_ACCESS_REQUIRED
- INVALID_NAME
- INVALID_PREFIX
- TOO_MANY_ORIGINS
- Account changed while creating the embed key. Try again.
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/3fa6fd9d83576f64.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/embed-keys.ts:90
*/
function embedKeyPrefix(plaintext: string): string {
return plaintext.slice(0, 9);
}
/**
* Create a new embed key for the current user.
* Returns the full plaintext key (shown once) and metadata.
*/
export async function createEmbedKey(name: string): Promise<CreateEmbedKeyResult> {
const userId = getCurrentClerkUser()?.id;
if (!userId) throw new Error('Sign in to create an embed key.');
const plaintext = generateEmbedKey();
const keyPrefix = embedKeyPrefix(plaintext);
const keyHash = await sha256Hex(plaintext);
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 creating the embed key. Try again.');
}
const result = await settleAccountOperation(
userId,
'creating the embed key',
() => client.mutation(
(api as any).embedKeys.createEmbedKey,
{ name: name.trim(), keyPrefix, keyHash },
),
);
assertAccountStillCurrent(userId, 'creating the embed key');
return { id: result.id, name: result.name, keyPrefix: result.keyPrefix, key: plaintext };
}
/** List all embed keys for the current user. */View on GitHub (pinned to 7d06c8633d)