koala73/worldmonitor · warning · Error
Webhook URL must use HTTPS
Error message
Webhook URL must use HTTPS
What it means
createApiKey() gates on getCurrentClerkUser() (src/services/clerk.ts:833), which returns the active Clerk session user or null. If no Clerk user is present, key creation stops before any plaintext key is minted and before any Convex call. This is a deliberate UX guard, not a network or backend failure.
Solutions
- Ensure the user is signed in and Clerk has fully loaded before enabling the create-key action
- Check ClerkProvider is mounted with a valid publishable key and the session has not expired
- Re-sign-in and retry; if it persists, inspect getCurrentClerkUser() in devtools
- Disable the create button when the auth state reports no user so the call is never made
Example fix
// before
await createApiKey(name); // throws 'Sign in to create an API key.' when signed out
// after
const user = getCurrentClerkUser();
if (!user?.id) {
openSignIn();
return;
}
await createApiKey(name); Defensive patterns
Strategy: validation
Validate before calling
const user = getCurrentClerkUser();
if (!user?.id) { openSignIn(); return; }
await createApiKey(name); Type guard
const hasActiveClerkUser = (u: { id: string } | null | undefined): u is { id: string } =>
typeof u?.id === 'string' && u.id.length > 0; Try / catch
try {
await createApiKey(name);
} catch (e) {
if (e instanceof Error && e.message === 'Sign in to create an API key.') openSignIn();
else toast(e instanceof Error ? e.message : String(e));
} Prevention
- Drive the create-key UI from live auth state, not cached UI state
- Disable key-management actions while Clerk is still loading
- Sign-in expiry is the top cause: prompt re-auth instead of letting the call throw
When it happens
Trigger: Invoking createApiKey(name) while signed out or after the Clerk session expired; calling it during app boot before Clerk finishes loading (race); Clerk publishable key missing so Clerk never yields a user; user signed out in another tab sharing the session.
Common situations: API-key settings UI rendered from cached state after logout; dev server started without Clerk env vars; silent token refresh failure leaving getCurrentClerkUser() null while the UI still shows controls.
Related errors
- buildAuthHeaders: free-tier context has no credentials — a…
- HTTP
- REDIS_DOWN
- Sign in to view your brief.
- Account changed while creating the embed key. Try again.
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-08-21).
Data as JSON: /api/errors/45550d68e61728ee.
Report an issue: GitHub.
Appendix: source
Thrown at api/_notification-webhook-ssrf.ts:239
async function defaultResolveHostname(hostname: string): Promise<string[]> {
const records = await Promise.all([
resolveDnsJson(hostname, 'A'),
resolveDnsJson(hostname, 'AAAA'),
]);
return records.flat();
}
/**
* Fail fast at registration when the webhook hostname currently resolves to a
* private or reserved address. Delivery repeats this check (and pins its
* connection) because DNS can change after registration.
*/
export async function assertNotificationWebhookRegistrationUrlSafe(
rawUrl: string,
resolveHostname: ResolveHostname = defaultResolveHostname,
): Promise<void> {
const staticError = blockedNotificationWebhookUrlReason(rawUrl);
if (staticError) throw new Error(staticError);
const hostname = new URL(rawUrl).hostname.toLowerCase();
if (isIpLiteral(hostname)) return;
let resolvedAddresses: string[];
try {
resolvedAddresses = await resolveHostname(hostname);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new Error(`Webhook URL DNS resolution failed: ${message}`);
}
if (!resolvedAddresses.length) throw new Error('Webhook URL DNS resolution returned no addresses');
if (resolvedAddresses.some(isBlockedNotificationResolvedAddress)) {
throw new Error('Webhook URL must not point to a private/local address');
}
}
View on GitHub (pinned to 7d06c8633d)