---
name: comfyui_validate_workflow
kind: function
lang: py
domain: ml
version: "1.0.0"
purity: impure
signature: "def comfyui_validate_workflow(workflow: dict, server: str = \"127.0.0.1:8188\", timeout: float = 30.0) -> dict"
description: "Valida un workflow ComfyUI (API format) contra el catalogo /object_info de un servidor vivo: cruza los class_type contra los nodos disponibles y los nombres de modelos (ckpt/lora/vae/controlnet/...) contra los combos enumerados de cada nodo. Devuelve nodos y modelos faltantes ANTES de encolar, evitando un HTTP 400. Compone comfyui_object_info. Impura: HTTP GET."
tags: [comfyui, ml, validation, workflow, stable-diffusion]
uses_functions: [comfyui_object_info_py_ml]
uses_types: []
returns: []
returns_optional: false
error_type: error_go_core
imports: []
params:
  - name: workflow
    desc: "dict en API format ({node_id: {class_type, inputs}}) a validar."
  - name: server
    desc: "host:port del servidor ComfyUI sin esquema. Debe estar vivo para consultar /object_info."
  - name: timeout
    desc: "Timeout de la consulta HTTP en segundos."
output: "dict {ok, valid, missing_nodes, missing_models, error}. ok = se pudo consultar el servidor; valid = sin nodos ni modelos faltantes; missing_nodes = class_type ausentes; missing_models = lista de {node, input, value} con valores de modelo fuera del combo; error = motivo si ok=False."
tested: false
tests: []
test_file_path: ""
file_path: "python/functions/ml/comfyui_validate_workflow.py"
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join(os.environ["HOME"], "fn_registry", "python", "functions"))
from ml.comfyui_build_txt2img_workflow import comfyui_build_txt2img_workflow
from ml.comfyui_validate_workflow import comfyui_validate_workflow

wf = comfyui_build_txt2img_workflow("IMG_dreamshaper_8.safetensors", "a cat")
res = comfyui_validate_workflow(wf)            # server 127.0.0.1:8188 vivo
# res == {"ok": True, "valid": True, "missing_nodes": [], "missing_models": [], "error": ""}

bad = comfyui_build_txt2img_workflow("no_existe.safetensors", "a cat")
res2 = comfyui_validate_workflow(bad)
# res2["valid"] == False
# res2["missing_models"] == [{"node": "4", "input": "ckpt_name", "value": "no_existe.safetensors"}]
```

El bloque de arriba se lanza con el python del venv. El `if __name__ == "__main__"` del archivo valida un txt2img de ejemplo contra el server local (`python/.venv/bin/python3 python/functions/ml/comfyui_validate_workflow.py`). Nota: `./fn run` posicional no aplica porque el primer arg es un dict (workflow), no un escalar de CLI.

## Cuando usarla

Siempre ANTES de `comfyui_submit_workflow`, sobre todo con workflows importados de
internet (JSON/PNG ajenos) o que mezclen checkpoints/LoRAs que quiza no tengas
descargados. Te dice exactamente que nodos custom faltan (a instalar) y que
modelos faltan (a descargar) sin gastar un encolado fallido en el servidor.

## Gotchas

- Impura: hace HTTP GET a `/object_info`. Requiere el servidor vivo; si esta caido
  o reiniciandose, devuelve `{ok: False, error: ...}` (no lanza). Reintenta tu.
- `missing_models` solo cubre inputs de modelo conocidos (ckpt_name, lora_name,
  vae_name, control_net_name, model_name, unet_name, clip_name, style_model_name,
  gligen_name) cuyo valor sea un string fuera del combo enumerado. No valida rangos
  numericos ni tipos de conexion.
- Detecta nodos custom faltantes por class_type ausente en /object_info, pero NO
  resuelve de que repo instalarlos (eso es trabajo de resolve_workflow_deps, P1).
- `sampler_name`/`scheduler` invalidos NO se reportan como missing_models (no son
  modelos); el servidor los rechazaria al encolar.
