n8n task runner rejections: poll a Sume job without losing it
n8n 2.41.6 keeps the task runner alive after an unhandled promise rejection. Make your Sume poll catch its own errors and stop only on a terminal status.

Write a Sume status poll so no promise can reject unhandled: wrap each status read in try/catch, back off between reads, and stop only when the job is completed, failed or canceled. A thrown network error is not a job outcome.
What the n8n release says
The n8n releases page lists n8n@2.41.6, dated Oct 2, 2026, with the entry "Keep the task runner running on an unhandled promise rejection". That keeps the runner process up. It does not make the lost work come back, so the poll itself should still be defensive.
Poll rules from the Sume docs
The Sume jobs page gives the rules for a client-side poll.
- Use exponential backoff, or honor
next_poll_after_secondswhen the status response carries it. - Stop on
completed,failedorcanceled. - Do not resubmit the original paid request because a local process timed out. Retrying the submit itself is fine with the same
Idempotency-Key. - A client-side timeout does not cancel the job; it keeps running and billing.
A poll that handles its own errors
This Node 18+ function reads status until a terminal state. A failed fetch counts as one failed attempt rather than an escape. It reads the terminal and sume_status fields the status endpoint returns.
const API = "https://api.sume.com";
const key = process.env.SUME_API_KEY;
if (!key) throw new Error("SUME_API_KEY is not set");
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
export async function pollJob(jobId, deadlineMs = 20 * 60 * 1000) {
const stop = Date.now() + deadlineMs;
let delay = 3000;
while (Date.now() < stop) {
try {
const res = await fetch(`${API}/v1/jobs/${jobId}/status`, {
headers: { Authorization: `Bearer ${key}` },
});
if (res.ok) {
const s = await res.json();
if (s.terminal) return s;
delay = (s.next_poll_after_seconds ?? 0) * 1000 || delay;
}
} catch (err) {
console.error("status read failed, will retry", err.message);
}
await sleep(delay);
delay = Math.min(delay * 2, 30000);
}
return { terminal: false, job_id: jobId, note: "deadline reached; job may still be running" };
}Keep the job id outside the runner
Save the job id from the submit response somewhere durable before polling, such as a workflow data store. If the process dies mid-poll, a new run can resume from GET /v1/jobs/{id}/status. When the status is completed, call GET /v1/jobs/{id}/result once; before that it answers 409 job_not_completed.
For long video jobs, a webhook is cheaper than a long poll. Webhooks carry only the terminal events and are retried up to 10 attempts, so keep polling available for deliveries that never arrive.
Sources
Related posts
More in Integrations
- Notion custom MCP connections: add Sume read-only first
Notion 3.7 adds custom MCP connections with approvals. Connect Sume's hosted MCP endpoint with the default read-only OAuth scope, then turn on writes.
- OpenAI Agents SDK 0.23 MCP listing limits and Sume tools
openai-agents-python 0.23 adds configurable MCP listing page limits. What that means for Sume's hosted MCP, where the tool list depends on your OAuth scope.
- OpenClaw cron tool allowlists for unattended jobs that call Sume
OpenClaw v2026.8.35 keeps explicit cron tool allowlists. Name the Sume tools a job may call, and pair them with a read-only OAuth grant or a capped key.
- Retool agent can create a REST resource: set it up for Sume
Retool's app builder agent can now create REST API resources from a prompt. Tell it the Sume base URL, one auth header and a free GET /v1/me test.
Written by Sume