affaan-m/ECC · error · Error

Discord announcement credentials are missing or invalid

Error message

Discord announcement credentials are missing or invalid

What it means

If no channel webhook is configured, the script falls back to bot-token delivery: it reads recent channel messages via the Discord API to check for an existing receipt, then posts and pins the announcement. This requires DISCORD_BOT_TOKEN and a numeric DISCORD_ANNOUNCE_CHANNEL_ID. It throws this error when either is missing or the channel id is not a 10-25 digit snowflake.

Solutions

  1. Set DISCORD_BOT_TOKEN secret and export it into the workflow env
  2. Set DISCORD_ANNOUNCE_CHANNEL_ID to the numeric channel id (enable Developer Mode in Discord, right-click channel, Copy ID)
  3. Alternatively configure DISCORD_ANNOUNCE_WEBHOOK_URL to use webhook delivery instead
  4. Verify secret names match exactly what the script reads

Example fix

// before
DISCORD_ANNOUNCE_CHANNEL_ID: "#announcements"
// after
DISCORD_ANNOUNCE_CHANNEL_ID: "1234567890123456789"
Defensive patterns

Strategy: validation

Validate before calling

const ok = !!process.env.DISCORD_BOT_TOKEN && /^\d{10,25}$/.test(process.env.DISCORD_ANNOUNCE_CHANNEL_ID || ''); if (!ok) throw new Error('Set DISCORD_BOT_TOKEN and a numeric DISCORD_ANNOUNCE_CHANNEL_ID');

Type guard

const isValidChannelId = (v) => typeof v === 'string' && /^\d{10,25}$/.test(v);

Try / catch

try { await deliver(discussion); } catch (e) { if (/credentials are missing or invalid/.test(e.message)) { console.error('Configure bot token + numeric channel id (or a webhook URL)'); process.exit(1); } throw e; }

Prevention

When it happens

Trigger: deliver() runs with DISCORD_ANNOUNCE_WEBHOOK_URL unset and either DISCORD_BOT_TOKEN empty or DISCORD_ANNOUNCE_CHANNEL_ID absent/failed the /^\d{10,25}$/ test.

Common situations: Workflow has neither delivery method configured; channel id copied with a prefix or from a server that no longer exists; secrets not passed into the job environment; typos in env var names.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/6042b1ec305363c5. Report an issue: GitHub.

Appendix: source

Thrown at scripts/discord/release-announce.mjs:183

    const response = await request(webhookUrl, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    });
    if (!response.ok) {
      await deleteReceiptComment(claimId);
      throw new Error(`Discord webhook request failed (${response.status})`);
    }
    const message = await response.json();
    await addReceiptComment(discussion.id, `${marker}\n\nDiscord delivery: complete (message ${message.id}).`);
    await deleteReceiptComment(claimId).catch(() => {
      console.warn('announcement delivered; pending receipt cleanup requires attention');
    });
    console.log('announcement delivered by channel webhook');
    return;
  }
  if (!env.DISCORD_BOT_TOKEN || !/^\d{10,25}$/.test(env.DISCORD_ANNOUNCE_CHANNEL_ID || '')) {
    throw new Error('Discord announcement credentials are missing or invalid');
  }
  const recent = await discord('GET', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/messages?limit=100`);
  const receipt = findDiscordReceipt(recent, key);
  if (receipt) {
    await discord('PUT', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/pins/${receipt.id}`);
    console.log('announcement already delivered; pin verified');
    return;
  }
  const message = await discord('POST', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/messages`, buildDiscordPayload({
    title: discussion.title,
    body: discussion.body,
    url: discussion.url,
    key,
  }));
  await discord('PUT', `/channels/${env.DISCORD_ANNOUNCE_CHANNEL_ID}/pins/${message.id}`);
  console.log('announcement delivered and pinned');
}

View on GitHub (pinned to 8321021c54)