Skip to main content

The host loads V1 instead of V2

Confirm that the pack still has its V1 distribution at the installation root and a complete replacement V2 distribution directly under v2/. The V2 entrypoint must be v2/__init__.py, not a replacement root entrypoint and not v2/v2/__init__.py. Repeat the pack’s required module, frontend, dependency, metadata, and asset layout inside v2/. The V2 loader treats that directory as the pack root and does not merge or recursively discover fallback files from the root V1 tree.

A required capability is unavailable

comfy.require() throws when the host does not implement or grant the capability. Probe optional behavior with comfy.supports() and degrade cleanly when it is absent. Report the missing capability by name and explain the use case it prevents; the API can add new capabilities and extension points. A private application import is not a stable fallback.

A frontend handle reports isDeleted

The node, widget, or document session ended. Release pack-owned state and reacquire a handle from the current graph or lifecycle event. Do not keep polling the deleted handle.

Two handles are not ===

They may come from different graph scopes or API instances. Use comfy.sameEntity(a, b). Use comfy.adopt() when you need a node handle in the current API instance.

A backend request returns 401

Use comfy.backend.fetch('/route'). backend.url() only builds a string, and a bare browser fetch() does not receive host authentication.

A static asset returns 404

For a file next to the JavaScript module, resolve it relative to import.meta.url:
Do not guess the installed pack directory. Use backend.assetUrl() only for a host-served absolute path the pack already knows. For a converted pack, also confirm that the asset exists inside the V2 distribution at the same relative location expected by the V2 module. A similarly named file in the root V1 tree is not the V2 asset.

A graph edit creates several undo steps

Wrap synchronous related mutations in comfy.graph.batch(). Do not keep a batch open across asynchronous work.

A widget value is missing from saved workflows or prompts

Check serialize, sendToPrompt, widget ordering, and beforeSerialize handling. Saved workflow, prompt, and embedded workflow are separate destinations.