Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Fix unhandled promise rejections in workflow error handling - #1

Merged
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library
Oct 29, 2025
Merged

Fix unhandled promise rejections in workflow error handling#1
igorls merged 5 commits into
mainfrom
copilot/handle-errors-in-comfyui-library

Conversation

CopilotAI commented Oct 29, 2025

Copy link
Copy Markdown
Contributor

When workflow enqueue operations fail, unhandled promise rejections crash the process. This violates the design goal of providing a robust library for server-side usage that gracefully handles all errors.

Changes

workflow.ts

  • Added .catch() handler to exec() invocation when not using a pool (line 417) - the async function was previously called without error handling
  • Added no-op .catch() to donePromise on creation (line 63) - prevents runtime from detecting unhandled rejection when promise is rejected before user code awaits done()

test/enqueue-failures.spec.ts

  • Added tests verifying workflow.run() handles enqueue failures without process crashes
  • Tests confirm errors propagate correctly through promise chain and failed events are emitted

Example

Before this fix, the following would crash the process:

constclient=newComfyApi("http://localhost:8188");constwf=Workflow.from(workflowJSON);try{constjob=awaitclient.run(wf);constresult=awaitjob.done();}catch(err){// Error would crash process before reaching hereconsole.error("Handled:",err);}

After the fix, errors are properly caught and the process remains stable.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • x
    • Triggering command: bun test (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

this issue cannot happen, when the library is used via WorkflowPool no errors should crash it, they must be gracefully handled, our goal is to design a robust comfyui library for server-side usage, that by default is able to handle adverse scenarios without crashes

bun run scripts/two-stage-edit-simulation.ts
[2025-10-29T16:16:21.145Z] Two-stage edit simulation starting {
hosts: [ "http://localhost:8188", "http://afterpic-comfy-aero16:8188", "http://afterpic-comfy-domi:8188" ],
runtimeHours: 6,
minDelayMs: 30000,
maxDelayMs: 240000,
seedStrategy: "random",
}
[2025-10-29T16:16:22.250Z] Starting first cycle immediately
[2025-10-29T16:16:22.250Z] ▶️ [http://afterpic-comfy-domi:8188] Generation run #1 seed=1753525260
[debug] emitFailure start EnqueueFailedError
[debug] emitFailure end EnqueueFailedError
[2025-10-29T16:16:22.260Z] ⚠️ Marking http://afterpic-comfy-domi:8188 as generation-incapable (Failed to queue prompt)
[2025-10-29T16:16:22.260Z] Starting first cycle immediately
[2025-10-29T16:16:22.260Z] ▶️ [http://localhost:8188] Generation run #1 seed=1544804889
42 | } else {
43 | bodyTextSnippet = JSON.stringify(bodyJSON).slice(0, 500);
44 | }
45 |
46 | const reason = extractReason(bodyJSON) || bodyTextSnippet;
47 | return new EnqueueFailedError("Failed to queue prompt", {
^
EnqueueFailedError: Failed to queue prompt
status: 400,
statusText: "Bad Request",
url: "http://afterpic-comfy-domi:8188/prompt",
method: undefined,
bodyJSON: {
error: [Object ...],
node_errors: [Object ...],
},
bodyTextSnippet: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\"
:{}},\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", reason: "{\"error\":{\"type\":\"prompt_outputs_failed_validation\",\"message\":\"Prompt outputs failed validation\",\"details\":\"\",\"extra_info\":{}},
\"node_errors\":{\"6\":{\"errors\":[{\"type\":\"value_not_in_list\",\"message\":\"Value not in list\",\"details\":\"ckpt_name: 'novaAnimeXL_ilV125.safetensors' not in []\",\"extra_info\":{\"input_name\":\"ckpt_name\",\"input_config\":[[],{\"tooltip\":\"The name of the checkpoint (model) to load.\"}],\"received_value\":\"novaAnimeXL_ilV125.safetensors\"}}],\"dependent_outputs\":[\"12\"],\"class_type\":\"Checkpoi", code: "E_ENQUEUE_FAILED"
at buildEnqueueFailedError (D:\GitHub\comfyui-node\src\utils\response-error.ts:47:10)
at async queuePrompt (D:\GitHub\comfyui-node\src\features\queue.ts:49:25)
at async appendPrompt (D:\GitHub\comfyui-node\src\features\queue.ts:60:25)
at async enqueueJob (D:\GitHub\comfyui-node\src\call-wrapper.ts:456:41)
at async run (D:\GitHub\comfyui-node\src\call-wrapper.ts:203:28)
at async <anonymous> (D:\GitHub\comfyui-node\src\workflow.ts:409:31)
Bun v1.3.2-canary.34+6580b563b (Windows x64)

Created from VS Code via the GitHub Pull Request extension.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

CopilotAIand others added 4 commits October 29, 2025 16:22
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
- Add .catch() handler to exec() when not using pool to prevent unhandled rejections
- Add .catch() handler to donePromise to prevent unhandled rejection warnings
- Add tests to verify error handling works correctly without crashing
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
Co-authored-by: igorls <4753812+igorls@users.noreply.github.com>
CopilotAI changed the title [WIP] Add error handling for WorkflowPool scenariosFix unhandled promise rejections in workflow error handlingOct 29, 2025
CopilotAI requested a review from igorlsOctober 29, 2025 16:35
@igorls
igorls marked this pull request as ready for review October 29, 2025 20:57
CopilotAI review requested due to automatic review settings October 29, 2025 20:57
@igorls
igorls merged commit 405b78b into mainOct 29, 2025
@igorls
igorls deleted the copilot/handle-errors-in-comfyui-library branch October 29, 2025 20:57

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes unhandled promise rejection warnings that occur during workflow enqueue failures when no pool is used. The fix ensures that promise rejections in the exec() function are properly caught and handled by attaching error handlers.

Key changes:

  • Added .catch() handler to exec() call when no pool is used
  • Added a no-op catch handler to donePromise in WorkflowJob constructor to prevent unhandled rejection warnings
  • Added comprehensive tests for enqueue failure scenarios without pool

Reviewed Changes

Copilot reviewed 2 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/workflow.tsAdded .catch() handler to exec() when no pool is used; added no-op catch to donePromise to suppress warnings
test/enqueue-failures.spec.tsAdded two new test cases covering enqueue failures without pool
dist/workflow.jsCompiled JavaScript output reflecting the source changes
dist/workflow.js.mapUpdated source map for compiled JavaScript
dist/workflow.d.ts.mapUpdated TypeScript declaration source map
bun.lockUpdated @types/bun dependency version

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

try {
await wf.run(api as any);
// If we reach here, the test should fail because run() should have thrown
expect(true).toBe(false); // Force test failure if no error was thrown

CopilotAIOct 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using expect(true).toBe(false) to force a test failure, use expect.fail() or simply omit this line—the test will naturally fail if no exception is thrown since the catch block won't be entered. Alternatively, restructure with await expect(wf.run(api as any)).rejects.toBeInstanceOf(EnqueueFailedError) for more idiomatic testing of async rejections.

Suggested change
expect(true).toBe(false);// Force test failure if no error was thrown
expect.fail();// Force test failure if no error was thrown

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@igorls