#22874: fix(slack): preserve numeric threadId for message read
size: XS
Cluster:
Slack Thread ID Fixes
## Summary
- Problem: Slack `message` read can drop numeric `threadId` values and return channel history instead of thread replies.
- Why it matters: models/tools often emit Slack timestamps as numbers; thread reads should still work.
- What changed: Slack read adapter now accepts string-or-number `threadId` and forwards numeric values as strings.
- What did NOT change (scope boundary): no broad parser behavior changes outside Slack read adapter.
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [x] Skills / tool execution
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #22852
- Related #15713
- Context #1450, #14948, #1442
## User-visible / Behavior Changes
- Slack `message` tool `read` preserves numeric `threadId` inputs by coercing to string before dispatch.
## Security Impact (required)
- New permissions/capabilities? (`Yes/No`) No
- Secrets/tokens handling changed? (`Yes/No`) No
- New/changed network calls? (`Yes/No`) No
- Command/tool execution surface changed? (`Yes/No`) No
- Data access scope changed? (`Yes/No`) No
- If any `Yes`, explain risk + mitigation:
## Repro + Verification
### Environment
- OS: macOS
- Runtime/container: Node + pnpm
- Integration/channel (if any): Slack
### Steps
1. Invoke Slack read with numeric `threadId`.
2. Observe adapter payload passed to Slack action handler.
### Expected
- Numeric `threadId` is forwarded as a non-empty string.
### Actual (before fix)
- `threadId` was dropped (`undefined`) and reads fell back to channel history.
## Evidence
- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
## Human Verification (required)
- Verified scenarios:
- `pnpm test -- src/channels/plugins/actions/actions.test.ts -t "forwards numeric threadId for read"` (failed before fix, passes after)
- `pnpm test -- src/channels/plugins/actions/actions.test.ts -t "slack actions adapter"`
- `pnpm test -- src/slack/actions.read.test.ts`
- Full suite check performed locally by operator: `pnpm build && pnpm check && pnpm test`
- Edge cases checked:
- Existing string `threadId` forwarding test remains passing.
- What you did **not** verify:
- Live Slack workspace E2E in this PR.
## Compatibility / Migration
- Backward compatible? (`Yes/No`) Yes
- Config/env changes? (`Yes/No`) No
- Migration needed? (`Yes/No`) No
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: revert this PR.
- Files/config to restore: `src/plugin-sdk/slack-message-actions.ts`, `src/channels/plugins/actions/actions.test.ts`, `CHANGELOG.md`.
- Known bad symptoms reviewers should watch for: Slack read thread queries returning channel history despite numeric `threadId` input.
## Risks and Mitigations
- Risk: Number coercion could accept unintended numeric values for `threadId`.
- Mitigation: change is intentionally scoped to Slack read adapter `threadId` parsing only.
## AI Assistance
- AI-assisted implementation and test drafting; validated by local test runs.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Fixed Slack `message` read to preserve numeric `threadId` values by using `readStringOrNumberParam` instead of `readStringParam`, preventing thread reads from falling back to channel history when LLM models emit timestamps as numbers.
- Scoped change to read action only in `src/plugin-sdk/slack-message-actions.ts:115`
- Added test coverage for numeric `threadId` conversion to string
- Maintains backward compatibility with existing string `threadId` inputs
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- The change is well-scoped to a single parameter parser in one action handler, includes proper test coverage verifying the numeric-to-string conversion, and maintains backward compatibility with existing string inputs. The implementation leverages an existing utility function (`readStringOrNumberParam`) that handles both types safely.
- No files require special attention
<sub>Last reviewed commit: a812e32</sub>
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#14720: fix(slack): pass threadId in plugin read action (#14706)
by lailoo · 2026-02-12
85.9%
#6509: fix(slack): pass threadId param in read action
by morningstar-daemon · 2026-02-01
84.8%
#22216: fix(slack): enable thread reply reading in slack extension plugin
by lan17 · 2026-02-20
84.5%
#5098: fix(slack): forward threadId for message.read
by galligan · 2026-01-31
82.7%
#22485: fix(slack): use threadId from delivery context as threadTs fallback...
by dorukardahan · 2026-02-21
80.0%
#4749: fix: handle string thread IDs in queue drain for Slack
by nvonpentz · 2026-01-30
79.5%
#20406: fix(slack): respect replyToMode when computing statusThreadTs in DMs
by QuinnYates · 2026-02-18
79.2%
#5514: Slack: fix threadId ignored on read + thread_broadcast dropped
by SanderHelgesen · 2026-01-31
78.8%
#6071: fix(cli): add --thread-id option to message read command
by lyra63237 · 2026-02-01
78.8%
#12199: fix(message): add threadId parameter to fetch schema for Slack thre...
by dbg-vanie · 2026-02-09
78.6%