paperclipai/paperclip · error
CHAT_PROVIDER_PRETRANSPORT_REJECTED
CHAT_PROVIDER_PRETRANSPORT_REJECTED
Error message
Invalid Slack session destination or status
What it means
setSlackSessionStatus performs pre-transport validation of the Slack session destination and status before calling the Slack agents.sessions.setStatus API. This error is thrown when the threadId is not a well-formed "slack:<channelId>:<threadTs>" value (channel ID must match SLACK_CHANNEL_ID, thread timestamp must match SLACK_TIMESTAMP, no extra segments) or the status is not one of processing/active/suspended/closed. It carries code CHAT_PROVIDER_PRETRANSPORT_REJECTED, meaning the request was rejected locally and never sent to Slack.
Solutions
- Log/inspect the exact input.threadId and input.status values at the call site and compare against the required format slack:<C1234567890>:<1234567890.123456> with exactly three segments
- Fix the code that produces or persists the session thread ID so it stores the canonical slack:channelId:threadTs form
- Constrain the status to the SlackSessionStatus union type so TypeScript rejects unknown statuses at compile time
- If this error surfaces at runtime, treat it as a local bug: do not retry (the request never reached Slack) and mark the session status update as failed per the idempotency contract
Example fix
// before
await setSlackSessionStatus({ botToken, threadId: session.threadUrl, status: "open" });
// after
const m = session.threadUrl.match(/slack\.com\/archives\/(?<ch>C\w+)\/p(?<ts>\d+)/);
const threadId = m ? `slack:${m.groups.ch}:${Number(m.groups.ts.slice(0,10))}.${Number(m.groups.ts.slice(10))}` : session.threadId;
await setSlackSessionStatus({ botToken, threadId, status: "active" satisfies SlackSessionStatus }); Defensive patterns
Strategy: validation
Validate before calling
const SLACK_CHANNEL_ID = /^C[A-Z0-9]{8,}$/;
const SLACK_TIMESTAMP = /^\d+\.\d+$/;
function validateSlackSession(threadId, status) {
const [, ch, ts, extra] = threadId.split(":");
if (!threadId.startsWith("slack:") || !SLACK_CHANNEL_ID.test(ch) || !SLACK_TIMESTAMP.test(ts) || extra !== undefined)
throw new Error(`bad threadId: ${threadId}`);
if (!["processing","active","suspended","closed"].includes(status)) throw new Error(`bad status: ${status}`);
} Type guard
const isSlackThreadId = (v: unknown): v is `slack:${string}` =>
typeof v === "string" && /^slack:C[A-Z0-9]+:\d+\.\d+$/.test(v); Try / catch
try {
await setSlackSessionStatus({ botToken, threadId, status });
} catch (e) {
if ((e as { code?: string }).code === "CHAT_PROVIDER_PRETRANSPORT_REJECTED") {
// local bug: never reached Slack; do NOT retry — log threadId shape and fix the producer
logger.error({ threadIdShape: String(threadId).split(":").length }, "invalid slack session input");
return "unavailable";
}
throw e;
} Prevention
- Always persist the canonical slack:<channelId>:<threadTs> triple at session creation time
- Type the status parameter as the SlackSessionStatus union so bad values fail at compile time
- Add a round-trip test: create a session, then update its status with the stored id
When it happens
Trigger: Calling setSlackSessionStatus with input.threadId that does not start with "slack:", has an empty or malformed channel ID, an empty or malformed thread timestamp, more than three colon-separated segments, or input.status outside ["processing","active","suspended","closed"].
Common situations: A thread ID was stored in the wrong format (e.g. a bare channel ID or a Slack permalink URL instead of the slack:channel:ts triple); a Discord/Teams thread identifier was passed to the Slack helper; a new status string like "idle" was introduced by a caller without updating this helper; a colon-containing value corrupted the split-based parsing.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- CHAT_PROVIDER_PRETRANSPORT_REJECTED
- External chat progress state is invalid
- External chat publications support at most
- External chat text exceeds its projected processing limit
- A full lowercase source SHA is required.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/ff7368cbd233603b.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/chat-slack-sessions.ts:118
botToken: string;
threadId: string;
status: SlackSessionStatus;
fetch?: typeof globalThis.fetch;
}): Promise<"updated" | "unavailable"> {
const [, channelId, threadTs, extra] = input.threadId.split(":");
if (
!input.threadId.startsWith("slack:") ||
!channelId ||
!SLACK_CHANNEL_ID.test(channelId) ||
!threadTs ||
!SLACK_TIMESTAMP.test(threadTs) ||
extra !== undefined ||
!["processing", "active", "suspended", "closed"].includes(input.status)
) {
throw Object.assign(
new Error("Invalid Slack session destination or status"),
{
code: "CHAT_PROVIDER_PRETRANSPORT_REJECTED",
},
);
}
let response: Response;
try {
response = await (input.fetch ?? globalThis.fetch)(
"https://slack.com/api/agents.sessions.setStatus",
{
method: "POST",
headers: {
authorization: `Bearer ${input.botToken}`,
"content-type": "application/json; charset=utf-8",
},
body: JSON.stringify({
channel_id: channelId,
thread_ts: threadTs,
status: input.status,
}),View on GitHub (pinned to 3f1d897a7c)