SDXL ControlNet in ComfyUI: Canny Setup and Error Fixes

Illustration for the SDXL ControlNet guide

ControlNet gives an SDXL workflow structural guidance from an image, such as edges, depth or pose. This guide shows the smallest useful ComfyUI graph and how to diagnose common connection errors. It is an editorial workflow reference, not a record of a hardware benchmark.

Visual guide: Trace an SDXL Canny control signal

Trace an SDXL Canny control signalReference image then Inspect the Canny edge map then Apply compatible SDXL ControlNet then Sample with conditioned inputs then Compare reference and result. Editorial process diagram, not an execution screenshot.FLUXDRAW / VISUAL WORKFLOW1Reference image2Inspect the Canny edge map3Apply compatible SDXL ControlNet4Sample with conditioned inputs5Compare reference and resultExplanatory map / not a benchmark or test result
Original FluxDraw explanatory map. Follow the stages with the checks below; the map is not a screenshot, a measured result or an executable workflow.

How to use this map

  1. Start with an SDXL graph that already saves an image. Add the control branch as a separate change so you can distinguish base failures from control failures.
  2. Inspect the Canny preview directly. Missing subject edges or excessive background lines can explain a weak result before any strength tuning.
  3. Connect the processed control map and compatible model through Apply ControlNet to the conditioning used by the sampler. The map alone is not the complete control signal.
  4. Hold the prompt and seed steady for the first strength comparison. Check whether the required layout is preserved and whether unwanted edges are being copied.

Stop and check: Do not mix control weights from a different model family. Save the original reference, preprocessor settings and control preview with the output.

Next practical guides: SDXL in ComfyUI: First Image, Base and Refiner Workflow · ComfyUI Queue Errors: Stuck Prompts and Missing Nodes

Implementation reference: Official ControlNet examples. Use the matching version-specific example alongside this editorial map.

Before you start

Install a current ComfyUI release and confirm that a basic SDXL text-to-image graph completes first. Download an SDXL base checkpoint and an SDXL-compatible ControlNet model from its official distribution page. Match the conditioning type to the model: a Canny model expects an edge map, while a depth model expects a depth map. Record the exact file names and versions you use.

Minimal graph

  1. Load the SDXL checkpoint with Load Checkpoint. Connect its model, CLIP and VAE outputs to the appropriate sampler, text-encoder and decoder nodes.
  2. Encode positive and negative prompts using the CLIP output. Start with a simple subject and background so you can see whether the structural image is affecting the result.
  3. Load the SDXL ControlNet file using Load ControlNet. Load the reference image and, if your model requires one, run the matching preprocessor. Check that the preprocessor output is the image you intended to supply.
  4. Connect positive and negative conditioning plus the ControlNet and processed image to Apply ControlNet. Feed its conditioned outputs to the sampler.
  5. Create the latent image at a suitable SDXL resolution, sample, decode with VAE and save the output.

The official ComfyUI ControlNet example shows the current node connections and provides example workflows. Node names and sockets can change, so use that page as the source for a current release.

A concrete SDXL Canny starting point

For an edge-guided example, start with SDXL base 1.0 and the publisher’s SDXL Canny ControlNet. The latter was trained for SDXL base with Canny conditioning. Download a weight format supported by your ComfyUI loader; the Python Diffusers example on a model card is not itself a ComfyUI workflow.

Keep the checkpoint under ComfyUI/models/checkpoints/ and the compatible ControlNet weights under ComfyUI/models/controlnet/. A filename ending in “sd15” should not be treated as an SDXL substitute. The general official ControlNet tutorial includes an SD 1.5 scribble example: use it to understand connections, not as the SDXL model download list.

Trace each connection before running

SourceDestinationCheck
Load Checkpoint: MODELKSampler: modelThe checkpoint is SDXL
Load Checkpoint: CLIPBoth text encodersPositive and negative use the same checkpoint’s encoder
Text conditioningApply ControlNet: positive and negativeDo not bypass the control branch
Load ControlNetApply ControlNet: control_netThe selected file matches SDXL and Canny
Edge-map imageApply ControlNet: imageInspect the map before sampling
Conditioned positive and negativeKSampler conditioningBoth outputs reach the sampler
Empty Latent ImageKSampler: latent_imageBatch size one for diagnosis
KSampler latent and checkpoint VAEVAE Decode → Save ImageDecode the sampled latent

If your Apply ControlNet node exposes a required VAE input, supply the workflow’s compatible VAE. Follow the sockets on your installed node rather than copying an older screenshot.

Control strength and timing

The advanced Apply ControlNet node exposes strength and start/end percentages. Strength sets the influence of the control signal; the percentages define when it is active during denoising. They are separate controls. A high strength with a short interval is not equivalent to a low strength over the whole interval.

For a first diagnostic run, keep the interval unchanged from the compatible example. Compare an unconditioned baseline with one conditioned run before tuning timing. If you change strength, prompt, edge thresholds and seed together, you lose the ability to identify the cause of a difference.

A small experiment you can reproduce

This is a proposed exercise, not a FluxDraw test result. Photograph a simple object against an uncluttered background, such as a cup on a table. Choose the output aspect ratio before making the edge map, and preserve that framing through preprocessing and generation. Cropping the map differently from the output can move the structure you wanted to keep.

  1. Save the original reference and a visible edge-map preview. Confirm the cup rim, handle and table boundary remain readable.
  2. Use a short brief, for example: “A ceramic cup on a wooden table, side lighting, neutral background.” Keep it consistent for all runs.
  3. Save the base SDXL output with ControlNet removed from the conditioning path.
  4. Run the conditioned graph with the example’s settings, using the same prompt, dimensions and fixed seed.
  5. Change only ControlNet strength for a second conditioned output. Label each image with its actual settings.
  6. Check handle placement, object silhouette, background flexibility and artifacts separately. Select the result that meets the brief, rather than the one with the most rigid edge match.

After this works, repeat with a new reference. A setting that worked for a clean cup outline may be unsuitable for hair, foliage or a noisy photograph.

When control looks wrong, inspect the map first

A dense edge map can include shadows and surface texture that should not become structural boundaries. A sparse map may lose the subject entirely. Before adding more sampling steps, check whether the map itself contains the useful outline. If it does not, adjust preprocessing and save another preview while keeping the generation settings fixed.

For pose or depth, choose the matching SDXL control model and its documented preprocessing. A Canny map cannot be silently swapped for a pose skeleton or depth image. Combining multiple controls adds more possible conflicts; establish one working control first.

What to save when asking for help

Include the ComfyUI version, checkpoint and ControlNet filenames, preprocessing method, workflow JSON, reference map, output and full error text. State whether plain SDXL works. Remove credentials and private reference images before sharing. This lets someone distinguish a model-loading problem from bad conditioning or a memory failure.

Test one change at a time

Keep the checkpoint, seed, prompt, sampler and resolution fixed while you vary ControlNet strength. Save a baseline image with no ControlNet and at least two conditioned results. Check whether the intended edges or pose were preserved and whether the image became rigid or distorted. The useful strength depends on the model, reference image and prompt; a number from another workflow is only a starting point.

Common failures

Model will not load

Confirm the ControlNet file is in the expected model directory and matches SDXL. Restart or refresh model lists after adding files. Do not assume an SD 1.5 ControlNet is interchangeable with an SDXL model.

Validation fails before sampling

Inspect the highlighted node and the validation error. Check that Apply ControlNet receives a ControlNet object and an image, and that the conditioning outputs feed the sampler. Missing custom nodes may require their documented installation steps; avoid installing an unknown node solely to silence an error.

Output ignores or overfits the reference

View the preprocessor image first. If it is blank or noisy, fix the source or preprocessing before changing the prompt. Then adjust conditioning strength in small increments while holding the seed constant.

CUDA out of memory

Try batch size one, a smaller image, and the default memory settings. Peak use may happen during sampling or VAE decoding. Note the failing node and your GPU memory before changing models or adding tiled decoding.

Related guides

For a basic SDXL pipeline, see SDXL in ComfyUI. For application-level errors, see ComfyUI queue troubleshooting. If you plan to submit workflows via Python, use the API guide.