koala73/worldmonitor · error · ConvexError
UNAUTHENTICATED
UNAUTHENTICATED
Error message
UNAUTHENTICATED
What it means
A ConvexError thrown by the setChannel mutation when ctx.auth.getUserIdentity() returns null, meaning the caller invoked the mutation without a valid authenticated identity (no auth token, expired session, or anonymous call). It fires before any channel fields are validated or written, preventing unauthenticated users from creating or modifying notificationChannels. It is a generic auth sentinel; the input at fault is the request itself lacking credentials. Clients must authenticate before calling setChannel.
Solutions
- Ensure the Clerk session is established before the channel-settings UI saves
- Handle the UNAUTHENTICATED ConvexError by prompting sign-in
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at convex/notificationChannels.ts:479 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-08-21).
Data as JSON: /api/errors/0d004ebd421b5293.
Report an issue: GitHub.
Appendix: source
Thrown at convex/notificationChannels.ts:518
.withIndex("by_user", (q) => q.eq("userId", identity.subject))
.collect();
return channels.map(channel => (channel.channelType === "email" && channel.emailOwnership !== "verified_account")
|| (channel.channelType === "telegram" && channel.telegramOwnership !== "verified_callback")
? { ...channel, verified: false } : channel);
},
});
export const setChannel = mutation({
args: {
channelType: channelTypeValidator,
chatId: v.optional(v.string()),
webhookEnvelope: v.optional(v.string()),
email: v.optional(v.string()),
webhookLabel: v.optional(v.string()),
},
handler: async (ctx, args) => {
const identity = await ctx.auth.getUserIdentity();
if (!identity) throw new ConvexError("UNAUTHENTICATED");
const userId = identity.subject;
await assertProEntitlement(ctx, userId);
const existing = await ctx.db
.query("notificationChannels")
.withIndex("by_user_channel", (q) =>
q.eq("userId", userId).eq("channelType", args.channelType),
)
.unique();
const now = Date.now();
if (args.channelType === "telegram") {
throw new ConvexError("telegram channel must be linked through bot pairing");
} else if (args.channelType === "slack") {
if (!args.webhookEnvelope) throw new ConvexError("webhookEnvelope required for slack channel");
const doc = { userId, channelType: "slack" as const, webhookEnvelope: args.webhookEnvelope, verified: true, linkedAt: now };
if (existing) {View on GitHub (pinned to e586b8b4b8)