koala73/worldmonitor · error · ConvexError
chatId required for telegram channel
Error message
chatId required for telegram channel
What it means
Thrown by `setChannel` when `channelType === "telegram"` but `args.chatId` is missing/empty. After auth and Pro-entitlement pass, the telegram branch requires a chatId to store. Plain-string ConvexError; `err.data === "chatId required for telegram channel"`. This is per-channel-type required-field validation — each branch (telegram/slack/email/webhook) has its own guard.
Source
Thrown at convex/notificationChannels.ts:493
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") {
if (!args.chatId) throw new ConvexError("chatId required for telegram channel");
const doc = { userId, channelType: "telegram" as const, chatId: args.chatId, verified: true, linkedAt: now };
if (existing) {
await ctx.db.replace(existing._id, doc);
} else {
await ctx.db.insert("notificationChannels", doc);
}
} 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) {
await ctx.db.replace(existing._id, doc);
} else {
await ctx.db.insert("notificationChannels", doc);
}
} else if (args.channelType === "email") {
if (!args.email) throw new ConvexError("email required for email channel");
const doc = { userId, channelType: "email" as const, email: args.email, verified: true, linkedAt: now };
if (existing) {View on GitHub (pinned to ffec79ac33)
Solutions
- Capture the Telegram chat id from the bot-link callback before calling `setChannel`.
- Client-side: disable the save button until `chatId` is non-empty for the telegram branch.
- On `err.data === "chatId required for telegram channel"`, show a field-level error and re-run the bot-link flow.
Example fix
// before
await convex.mutation(api.notificationChannels.setChannel, { channelType: "telegram" });
// after
if (channelType === "telegram" && !chatId) {
setFieldError("chatId", "Link your Telegram chat first.");
return;
}
await convex.mutation(api.notificationChannels.setChannel, { channelType: "telegram", chatId }); Defensive patterns
Strategy: validation
Validate before calling
if (channelType === "telegram" && !chatId) {
setFieldError("chatId", "Link your Telegram chat first.");
return;
} Type guard
function hasTelegramChatId(args: { channelType: string; chatId?: string }): boolean {
return args.channelType !== "telegram" || (typeof args.chatId === "string" && args.chatId.length > 0);
} Try / catch
try {
await convex.mutation(api.notificationChannels.setChannel, { channelType: "telegram", chatId });
} catch (err) {
if (err.data === "chatId required for telegram channel") setFieldError("chatId", "Link your Telegram chat first.");
else throw err;
} Prevention
- Capture the Telegram chat id from the bot-link callback before calling setChannel.
- Disable save until chatId is non-empty for the telegram branch.
- Run the full bot-link flow if chatId is missing.
- Plain-string error — branch on the exact message.
When it happens
Trigger: Calling `setChannel({ channelType: "telegram" })` with no `chatId`; `chatId` is an empty string or undefined; the Telegram OAuth/link flow didn't yield a chat id before the mutation fired.
Common situations: The Telegram bot-link flow completed the auth step but the chat id wasn't captured; a UI form that submits the channel type before the chat id field is populated; a test calling the mutation with only the channel type.
Related errors
- INCOMPATIBLE_DELIVERY
- COUNTRIES_LIMIT_EXCEEDED
- TICKERS_LIMIT_EXCEEDED
- digestHour must be an integer 0–23
- digestTimezone must be a valid IANA timezone (e.g. America/N
AI-assisted analysis of koala73/worldmonitor@ffec79ac33 (2026-08-12).
Data as JSON: /api/errors/a071d12540763eae.
Report an issue: GitHub.