diff --git a/nodes/_base.py b/nodes/_base.py index f407f38..7e79fa7 100644 --- a/nodes/_base.py +++ b/nodes/_base.py @@ -76,3 +76,15 @@ class OpRegistry: def all_op_ids(self) -> list[str]: return sorted(self.ops.keys()) + + +class OutputNotProducedError(RuntimeError): + """Raised when a workflow wires an opaque output (MODEL/CLIP/VAE) that the active mode does not produce.""" + + def __init__(self, *, slot_name: str, op_id: str) -> None: + self.slot_name = slot_name + self.op_id = op_id + super().__init__( + f"Operation '{op_id}' does not produce a '{slot_name}' output — " + f"disconnect that slot or pick a different mode." + ) diff --git a/tests/unit/test_base_errors.py b/tests/unit/test_base_errors.py new file mode 100644 index 0000000..8022174 --- /dev/null +++ b/tests/unit/test_base_errors.py @@ -0,0 +1,19 @@ +"""Tests for OutputNotProducedError — raised when opaque-type slots are wired but unfilled.""" + +from nodes._base import OutputNotProducedError + + +def test_error_is_runtime_error_subclass(): + assert issubclass(OutputNotProducedError, RuntimeError) + + +def test_error_message_includes_slot_name_and_op_id(): + err = OutputNotProducedError(slot_name="model", op_id="for_loop") + assert "model" in str(err) + assert "for_loop" in str(err) + + +def test_error_attributes_are_accessible(): + err = OutputNotProducedError(slot_name="clip", op_id="echo") + assert err.slot_name == "clip" + assert err.op_id == "echo"