{"record":{"id":"5926a814924eb314","repo":"sveltejs/kit","slug":"cannot-add-tasks-to-a-queue-that-has-ended","errorCode":null,"errorMessage":"Cannot add tasks to a queue that has ended","messagePattern":"Cannot add tasks to a queue that has ended","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/kit/src/core/postbuild/queue.js","lineNumber":52,"sourceCode":"\t\t\t\t\t.then(task.fulfil, (err) => {\n\t\t\t\t\t\ttask.reject(err);\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t})\n\t\t\t\t\t.then(() => {\n\t\t\t\t\t\tcurrent -= 1;\n\t\t\t\t\t\tdequeue();\n\t\t\t\t\t});\n\t\t\t} else if (current === 0) {\n\t\t\t\tclosed = true;\n\t\t\t\tresolve();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\t/** @param {() => any} fn */\n\t\tadd: (fn) => {\n\t\t\tif (closed) throw new Error('Cannot add tasks to a queue that has ended');\n\n\t\t\tconst promise = new Promise((fulfil, reject) => {\n\t\t\t\ttasks.push({ fn, fulfil, reject });\n\t\t\t});\n\t\t\tpromise.catch(() => {});\n\n\t\t\tdequeue();\n\t\t\treturn promise;\n\t\t},\n\n\t\tdone: () => {\n\t\t\tif (current === 0) {\n\t\t\t\tclosed = true;\n\t\t\t\tresolve();\n\t\t\t}\n\n\t\t\treturn promise;\n\t\t}","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/core/postbuild/queue.js#L34-L70","documentation":"SvelteKit's internal task queue (used during prerendering/build) exposes add() for scheduling work. Once q.end() is called the queue is closed; adding more tasks afterwards throws this error. It indicates scheduling work after the build phase has been finalized.","triggerScenarios":"Calling q.add(fn) after q.end() on the queue returned by create_queue — in practice, code or a plugin hook that enqueues prerender/render tasks after the prerender step completes.","commonSituations":"Custom build tooling integrating with Kit internals; async callbacks resolving after q.end() and then trying to add work; misordered lifecycle code in postbuild scripts.","solutions":["Ensure all q.add() calls complete before invoking q.end() — await outstanding tasks first","Reorder code so end() is only called after every producer has finished enqueueing","Track closed state in your wrapper and skip/queue-later instead of calling add after end","If triggered by a plugin, update the plugin to a version compatible with your @sveltejs/kit build pipeline"],"exampleFix":"// before\nawait Promise.all(items.map((i) => q.add(() => render(i))));\nq.end();\nstragglers.forEach((i) => q.add(() => render(i))); // throws\n\n// after\nfor (const i of items) await q.add(() => render(i));\nfor (const i of stragglers) await q.add(() => render(i));\nq.end();","handlingStrategy":"try-catch","validationCode":"function safeAdd(q, closed, fn) {\n  if (closed) return Promise.resolve();\n  return q.add(fn);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await q.add(task);\n} catch (e) {\n  if (String(e.message).includes('queue that has ended')) {\n    console.warn('Queue closed; run task directly or reschedule');\n    return task();\n  }\n  throw e;\n}","preventionTips":["Await every q.add() promise before calling q.end()","Never enqueue from callbacks that can resolve after teardown","Keep one owner of the queue lifecycle in your build code"],"tags":["build","queue","lifecycle"],"backgroundTag":"queue-already-ended","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}