Skip to content

fix(discord): fall back to env vars in mergeCredentials when credentials not explicitly set#150

Open
tonystrawberry wants to merge 4 commits into
vercel:mainfrom
tonystrawberry:fix/discord-bot-token-env-fallback
Open

fix(discord): fall back to env vars in mergeCredentials when credentials not explicitly set#150
tonystrawberry wants to merge 4 commits into
vercel:mainfrom
tonystrawberry:fix/discord-bot-token-env-fallback

Conversation

@tonystrawberry

Copy link
Copy Markdown

Problem

When discordChannel() is used without an explicit credentials option (the common case), scheduled and proactive sessions always get HTTP 401 from Discord.

mergeCredentials returns botToken: undefined when no credentials are passed. callDiscordApi gates the Authorization header on !== undefined, so the block is skipped entirely — no auth header is sent, Discord returns 401. The env var fallback inside resolveDiscordBotToken is never reached.

This only affects scheduled/proactive sessions (e.g. receive(discord, { target, auth: appAuth }) from a schedule handler). Slash command sessions are unaffected because they use an interaction token for the initial deferred reply.

Fix

Default botToken and publicKey to lazy env var readers in mergeCredentials, consistent with how resolveDiscordBotToken already handles the function variant.

Workaround

Until this is patched, pass credentials explicitly to discordChannel():

export default discordChannel({
  credentials: {
    applicationId: () => process.env.DISCORD_APPLICATION_ID!,
    botToken: () => process.env.DISCORD_BOT_TOKEN!,
    publicKey: () => process.env.DISCORD_PUBLIC_KEY!,
  },
});

Fixes #149

… and public key

When discordChannel() is called without explicit credentials, mergeCredentials
returned botToken: undefined. callDiscordApi gates auth on !== undefined, so
the Authorization header was never set and Discord returned 401.

Fix by defaulting to lazy env var readers so the fallback is always reachable.
Fixes vercel#149
@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

@tonystrawberry is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

I, Tony Duong <tony.duong.102@gmail.com>, hereby add my Signed-off-by to this commit: edb54e6

Signed-off-by: Tony Duong <tony.duong.102@gmail.com>
Comment thread packages/eve/src/public/channels/discord/discordChannel.ts Outdated
… mergeCredentials

Signed-off-by: Tony Duong <tony.duong.102@gmail.com>
…eCredentials

process.env.* returns string | undefined; DiscordBotToken requires
() => string | Promise<string>. The non-null assertion satisfies the
type — resolveDiscordBotToken throws at runtime if the var is absent.

Signed-off-by: Tony Duong <tony.duong.102@gmail.com>
@@ -679,8 +679,8 @@ function mergeCredentials(
): DiscordChannelCredentials {
const merged: DiscordChannelCredentials = {
applicationId: state.applicationId ?? credentials?.applicationId,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding DISCORD_APPLICATION_ID, resolveDiscordApplicationId is called unconditionally and already handles undefined by falling back to process.env.DISCORD_APPLICATION_ID so it's fine here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord channel 401: bot token env var fallback unreachable when credentials not passed to discordChannel()

1 participant