#22524: fix(doctor): preserve precision of large Discord snowflake IDs in --fix
commands
size: S
Cluster:
Discord and MS Teams Fixes
## Summary
- Problem: `doctor --fix` silently corrupts Discord snowflake IDs that exceed `Number.MAX_SAFE_INTEGER`. `JSON5.parse()` rounds the bare integer, then the repair stringifies the lossy number — producing a valid-looking but wrong ID.
- Why it matters: The original Discord ID digits are lost permanently, breaking authorization.
- What changed: `maybeRepairDiscordNumericIds` now accepts the raw config file text and extracts original digit sequences via regex before conversion. Handles collisions where multiple distinct IDs round to the same `Number` by consuming originals in file order.
- What did NOT change (scope boundary): No changes to schema validation, config parsing, or other repair functions.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [x] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Related #18220 (introduced the Discord ID string requirement and `doctor --fix` repair)
## User-visible / Behavior Changes
- `doctor --fix` now preserves the exact original digits of large Discord IDs instead of silently truncating them.
- Change output includes `(recovered original precision from file)` when raw text recovery is used.
## Security Impact (required)
- New permissions/capabilities? No
- Secrets/tokens handling changed? No
- New/changed network calls? No
- Command/tool execution surface changed? No
- Data access scope changed? No
## Repro + Verification
### Environment
- OS: Any
- Runtime/container: Node.js
- Integration/channel (if any): Discord
### Steps
1. Write `openclaw.json` with a bare numeric Discord ID exceeding MAX_SAFE_INTEGER, e.g. `{ "channels": { "discord": { "allowFrom": [100000000000000001] } } }`
2. Run `openclaw doctor --fix`
3. Check the written config
### Expected
- `allowFrom` contains `"100000000000000001"` (original digits preserved)
### Actual
- Before fix: `allowFrom` contains `"100000000000000000"` (truncated)
- After fix: `allowFrom` contains `"100000000000000001"` (correct)
## Evidence
- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
Two new e2e tests: single large ID precision preservation, and multiple IDs that round to the same `Number`.
## Human Verification (required)
- Verified scenarios: All 14 e2e tests pass including 2 new precision tests
- Edge cases checked: Multiple IDs colliding to same lossy Number value
- What you did **not** verify: Manual end-to-end run with a real Discord bot token
## Compatibility / Migration
- Backward compatible? Yes
- Config/env changes? No
- Migration needed? No
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: Revert commit; the repair falls back to `String(entry)` when raw text is unavailable
- Files/config to restore: None
- Known bad symptoms reviewers should watch for: Discord IDs in config not matching expected values after doctor --fix
## Risks and Mitigations
- Risk: Regex extracts a bare integer from raw text that isn't actually a Discord ID (e.g. in a comment or unrelated field).
- Mitigation: The lookup is keyed by the lossy Number value, so it only matches when the parsed config already contains that exact number in a Discord ID list. False positives would require an unrelated bare integer that happens to round to the same Number as a Discord ID in the same config file.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR fixes a critical data corruption bug in `doctor --fix` where large Discord snowflake IDs exceeding `Number.MAX_SAFE_INTEGER` were silently truncated during repair.
**Key changes:**
- `maybeRepairDiscordNumericIds` now accepts raw config file text and extracts original digit sequences via regex before JSON parsing
- Handles collision cases where multiple distinct IDs round to the same `Number` by storing them in an array and consuming in file order (matching JSON parse order)
- Scopes regex extraction to only the Discord config section using brace-depth tracking with proper string literal handling
- Adds string-skipping logic to correctly handle braces and quotes inside JSON strings
- Includes comprehensive test coverage for both single large ID preservation and collision scenarios
All previously identified issues from review threads have been addressed.
<h3>Confidence Score: 4/5</h3>
- Safe to merge with minor risk around edge cases in Discord config section extraction
- All previously identified critical bugs have been fixed (map collisions, string handling, test coverage). The implementation correctly handles the complex case of multiple IDs rounding to the same Number. String-skipping logic properly handles escape sequences. However, deducting one point because the regex-based extraction from raw text could theoretically match unrelated 16+ digit numbers in comments or other Discord fields that happen to round to the same value as actual IDs, though this is acknowledged as a known risk with reasonable mitigation.
- No files require special attention - all critical issues from previous review have been addressed
<sub>Last reviewed commit: 9791c9c</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#22557: fix(discord): coerce exec approval approver IDs to string to preven...
by zwffff · 2026-02-21
88.9%
#21240: fix: GH#20607 prevent doctor from dropping custom config sections
by theognis1002 · 2026-02-19
79.1%
#21463: fix(discord): prevent WebSocket death spiral + fix numeric channel ID…
by akropp · 2026-02-20
79.0%
#22408: fix: doctor --fix now persists config when removing unrecognized keys
by astroclaw · 2026-02-21
78.7%
#22342: fix(doctor): --fix now actually removes unrecognized config keys
by MisterGuy420 · 2026-02-21
78.5%
#12204: fix(discord): resolve numeric guildId/channelId pairs in channel al...
by mcaxtr · 2026-02-09
78.4%
#19401: fix(ui): prevent precision loss when coercing large numeric strings...
by Operative-001 · 2026-02-17
78.2%
#22501: fix(doctor): preserve logging config in doctor --fix
by Shuai-DaiDai · 2026-02-21
77.1%
#23432: Doctor: prevent permissive secret file modes during --fix
by bmendonca3 · 2026-02-22
76.4%
#8648: fix: don't treat bare numeric Discord IDs as definitive target IDs
by dbottme · 2026-02-04
75.5%