Skip to content

fix(discord): resolve numeric guildId/channelId pairs in channel allowlist#12204

Closed
mcaxtr wants to merge 5 commits intoopenclaw:mainfrom
mcaxtr:fix/12185-discord-numeric-channel-id
Closed

fix(discord): resolve numeric guildId/channelId pairs in channel allowlist#12204
mcaxtr wants to merge 5 commits intoopenclaw:mainfrom
mcaxtr:fix/12185-discord-numeric-channel-id

Conversation

@mcaxtr
Copy link
Copy Markdown
Contributor

@mcaxtr mcaxtr commented Feb 9, 2026

Fixes #12185

Summary

When users configure Discord channel allowlists with numeric guildId/channelId pairs (e.g. 111222333/444555666), parseDiscordChannelInput treated the channel part as a channel name rather than an ID. This caused the resolution to attempt a name-based lookup against guild channels, which always failed for numeric IDs, silently dropping inbound messages from those channels.

Changes

  • Numeric channel ID detection: when both halves of guild/channel are all-digits, parse the channel part as channelId for direct API lookup
  • Guild membership validation: reject entries where the fetched channel belongs to a different guild than specified
  • Graceful error handling: catch 404/403 from channel lookups so one bad entry doesn't abort the entire batch
  • Guild context preservation: include guildId on unresolved results so downstream onboarding doesn't default to wildcard guild
  • Name fallback: when a numeric channel ID lookup fails and a guild was specified, fall back to name matching within that guild (supports channels with numeric names like "2024")

Test plan

  • "111222333/444555666" resolves via direct channel ID lookup (TDD — test written first)
  • "111222333/444555666" where channel belongs to different guild → resolved: false with note
  • "111222333/999000111" where channel ID is 404 → marks unresolved, doesn't abort batch, preserves guildId
  • "111222333/777888999" where channel ID is 403 → marks unresolved, doesn't abort batch
  • "111222333/2024" where "2024" is a channel name → falls back to name matching within guild
  • All 7 new tests fail before fix, pass after
  • All 12 existing discord test files pass (40+ tests)
  • pnpm build && pnpm check clean

Greptile Overview

Greptile Summary

This PR updates Discord allowlist parsing/resolution to correctly handle numeric guildId/channelId inputs by treating the channel segment as an ID (with optional guild-scoped name fallback on 404), adds a guild-membership consistency check for resolved channels, and improves channel fetch error classification (403 vs 404 vs invalid payload) so a single bad entry doesn’t abort batch resolution.

The main logic lives in src/discord/resolve-channels.ts, where parseDiscordChannelInput now returns {guildId, channelId} when both segments are all-digits, and fetchChannel now returns a discriminated FetchChannelResult to avoid conflating forbidden/not-found/invalid responses. src/discord/resolve-channels.test.ts adds coverage for the numeric-pair path, guild mismatch rejection, 404/403 behavior, and malformed payload handling.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk.
  • The changes are localized to Discord allowlist parsing/resolution, add targeted tests for the new numeric guildId/channelId path, and the new error classification avoids previously reported incorrect fallbacks. I did not find any additional deterministic logic issues in the diff beyond previously addressed threads.
  • No files require special attention

@openclaw-barnacle openclaw-barnacle bot added the channel: discord Channel integration: discord label Feb 9, 2026
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 9, 2026

Additional Comments (1)

src/discord/resolve-channels.ts
Duplicate guild lookup

parsed.guildId && guilds.find(...) ? guilds.find(...) : ... performs the same find twice. This isn’t just style: because it’s inside the main resolution loop, it doubles work for guildOnly entries and makes behavior harder to reason about if this block ever changes (e.g. if guilds becomes non-static). Store the result of the first find and reuse it.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/discord/resolve-channels.ts
Line: 193:201

Comment:
**Duplicate guild lookup**

`parsed.guildId && guilds.find(...) ? guilds.find(...) : ...` performs the same `find` twice. This isn’t just style: because it’s inside the main resolution loop, it doubles work for `guildOnly` entries and makes behavior harder to reason about if this block ever changes (e.g. if `guilds` becomes non-static). Store the result of the first `find` and reuse it.

How can I resolve this? If you propose a fix, please make it concise.

@mcaxtr
Copy link
Copy Markdown
Contributor Author

mcaxtr commented Feb 9, 2026

Re: Duplicate guild lookup — Good catch, fixed in 307c26b. Both instances now store the find result in guildById and reuse it via nullish coalescing:

const guildById = parsed.guildId ? guilds.find((entry) => entry.id === parsed.guildId) : undefined;
const guild = guildById ?? (parsed.guild ? resolveGuildByName(guilds, parsed.guild) : undefined);

@greptile-apps could you please re-review? The duplicate lookup is resolved, and I've explained the numeric-name fallback rationale in the inline thread.

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@mcaxtr
Copy link
Copy Markdown
Contributor Author

mcaxtr commented Feb 9, 2026

@greptile-apps Great catch on the 403-vs-404 distinction — fixed in 1e0f4c5. fetchChannel now returns a discriminated union ("found" | "not-found" | "forbidden") so the name fallback only triggers on 404, not 403. New test confirms 403 stays hard-unresolved.

Could you please re-review?

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@mcaxtr
Copy link
Copy Markdown
Contributor Author

mcaxtr commented Feb 9, 2026

@greptile-apps Addressed both new comments:

Could you please re-review?

@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch 2 times, most recently from 9fdbc29 to 71a3650 Compare February 12, 2026 04:15
@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch from 71a3650 to ef5c6db Compare February 13, 2026 02:24
@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch from ef5c6db to af7d222 Compare February 13, 2026 14:35
@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch 8 times, most recently from a0ae671 to 1f1e0e1 Compare February 15, 2026 14:47
@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch 3 times, most recently from c54b6fd to 3ffa93a Compare February 19, 2026 03:21
@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch from 2420696 to 877a62e Compare February 27, 2026 15:46
@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch from 877a62e to d0999b2 Compare March 2, 2026 15:18
@mcaxtr
Copy link
Copy Markdown
Contributor Author

mcaxtr commented Mar 2, 2026

Rebase note: The numeric guildId/channelId parsing fix in parseDiscordChannelInput has since landed independently in main. This PR no longer carries that change.

What this PR still adds on top of current main:

  1. Error discrimination on fetchChannel — returns a FetchChannelResult discriminated union (found/not-found/forbidden/invalid) instead of DiscordChannelSummary | null. Without this, a single 404 or 403 from the Discord API throws an unhandled DiscordApiError and aborts the entire allowlist resolution batch.
  2. Name-based fallback — when a numeric channel ID lookup returns not-found and a guildId was specified, falls back to name matching within that guild (supports channels literally named with numbers like "2024").
  3. guildId preservation on unresolved results — the current failure path drops guildId, which causes downstream onboarding to default to wildcard guild.

Rebased onto current main — diff is clean against these three changes + corresponding tests.

mcaxtr added 5 commits March 3, 2026 01:09
…ling

Parse numeric channel part as channelId in guildId/channelId input format.
Validate guild membership to reject channels belonging to different guilds.
Handle 404 and 403 in fetchChannel to prevent batch abort on invalid or
inaccessible channel IDs. Preserve guildId context on unresolved lookups
so downstream code retains guild association.

Fixes openclaw#12185
…up fails

When a numeric channel ID cannot be resolved via the Discord API (404),
attempt name-based matching within the guild as a graceful degradation.
Deduplicate guild lookup logic that was repeated across the numeric and
name-based resolution paths.
…ect fallbacks

Distinguish 403 (access denied) from 404 (not found) so name-based
fallback only triggers on genuine not-found responses. Treat malformed
channel payloads (missing id/name) as invalid rather than not-found to
avoid incorrect name matching on corrupted API responses.
@mcaxtr mcaxtr force-pushed the fix/12185-discord-numeric-channel-id branch from d0999b2 to fb6c155 Compare March 3, 2026 04:09
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot bot commented Mar 3, 2026

🤖 We're reviewing this PR with Aisle

We're running a security check on the changes in this PR now. This usually takes a few minutes. ⌛
We'll post the results here as soon as they're ready.

Progress:

  • Analysis
  • Triage
  • Finalization

Latest run failed. Keeping previous successful results. Trace ID: 019cb1e33dee4672c27967d5094eba9b.

Last updated on: 2026-03-03T04:09:56Z

@thewilloftheshadow
Copy link
Copy Markdown
Member

Superseded by #33142 which consolidates the fixes from this PR. Closing this in favor of that PR.

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

Labels

channel: discord Channel integration: discord size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Discord inbound messages silently dropped after update — parseDiscordChannelInput fails to resolve numeric channel IDs

2 participants