Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
ComfyUI
Commits
73e85fb3
Commit
73e85fb3
authored
May 25, 2023
by
space-nuko
Browse files
Improve error output for failed nodes
parent
91449472
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
206 additions
and
35 deletions
+206
-35
execution.py
execution.py
+206
-35
No files found.
execution.py
View file @
73e85fb3
...
@@ -297,24 +297,80 @@ def validate_inputs(prompt, item, validated):
...
@@ -297,24 +297,80 @@ def validate_inputs(prompt, item, validated):
class_inputs
=
obj_class
.
INPUT_TYPES
()
class_inputs
=
obj_class
.
INPUT_TYPES
()
required_inputs
=
class_inputs
[
'required'
]
required_inputs
=
class_inputs
[
'required'
]
errors
=
[]
valid
=
True
for
x
in
required_inputs
:
for
x
in
required_inputs
:
if
x
not
in
inputs
:
if
x
not
in
inputs
:
return
(
False
,
"Required input is missing. {}, {}"
.
format
(
class_type
,
x
),
unique_id
)
error
=
{
"type"
:
"required_input_missing"
,
"message"
:
"Required input is missing"
,
"details"
:
f
"
{
x
}
"
,
"extra_info"
:
{
"input_name"
:
x
}
}
errors
.
append
(
error
)
continue
val
=
inputs
[
x
]
val
=
inputs
[
x
]
info
=
required_inputs
[
x
]
info
=
required_inputs
[
x
]
type_input
=
info
[
0
]
type_input
=
info
[
0
]
if
isinstance
(
val
,
list
):
if
isinstance
(
val
,
list
):
if
len
(
val
)
!=
2
:
if
len
(
val
)
!=
2
:
return
(
False
,
"Bad Input. {}, {}"
.
format
(
class_type
,
x
),
unique_id
)
error
=
{
"type"
:
"bad_linked_input"
,
"message"
:
"Bad linked input, must be a length-2 list of [node_id, slot_index]"
,
"details"
:
f
"
{
x
}
"
,
"extra_info"
:
{
"input_name"
:
x
,
"input_config"
:
info
,
"received_value"
:
val
}
}
errors
.
append
(
error
)
continue
o_id
=
val
[
0
]
o_id
=
val
[
0
]
o_class_type
=
prompt
[
o_id
][
'class_type'
]
o_class_type
=
prompt
[
o_id
][
'class_type'
]
r
=
nodes
.
NODE_CLASS_MAPPINGS
[
o_class_type
].
RETURN_TYPES
r
=
nodes
.
NODE_CLASS_MAPPINGS
[
o_class_type
].
RETURN_TYPES
if
r
[
val
[
1
]]
!=
type_input
:
if
r
[
val
[
1
]]
!=
type_input
:
return
(
False
,
"Return type mismatch. {}, {}, {} != {}"
.
format
(
class_type
,
x
,
r
[
val
[
1
]],
type_input
),
unique_id
)
received_type
=
r
[
val
[
1
]]
r
=
validate_inputs
(
prompt
,
o_id
,
validated
)
details
=
f
"
{
x
}
,
{
received_type
}
!=
{
type_input
}
"
if
r
[
0
]
==
False
:
error
=
{
validated
[
o_id
]
=
r
"type"
:
"return_type_mismatch"
,
return
r
"message"
:
"Return type mismatch between linked nodes"
,
"details"
:
details
,
"extra_info"
:
{
"input_name"
:
x
,
"input_config"
:
info
,
"received_type"
:
received_type
}
}
errors
.
append
(
error
)
continue
try
:
r
=
validate_inputs
(
prompt
,
o_id
,
validated
)
if
r
[
0
]
is
False
:
# `r` will be set in `validated[o_id]` already
valid
=
False
continue
except
Exception
as
ex
:
typ
,
_
,
tb
=
sys
.
exc_info
()
valid
=
False
error_type
=
full_type_name
(
typ
)
reasons
=
[{
"type"
:
"exception_during_validation"
,
"message"
:
"Exception when validating node"
,
"details"
:
str
(
ex
),
"extra_info"
:
{
"error_type"
:
error_type
,
"traceback"
:
traceback
.
format_tb
(
tb
)
}
}]
validated
[
o_id
]
=
(
False
,
reasons
,
o_id
)
continue
else
:
else
:
if
type_input
==
"INT"
:
if
type_input
==
"INT"
:
val
=
int
(
val
)
val
=
int
(
val
)
...
@@ -328,26 +384,97 @@ def validate_inputs(prompt, item, validated):
...
@@ -328,26 +384,97 @@ def validate_inputs(prompt, item, validated):
if
len
(
info
)
>
1
:
if
len
(
info
)
>
1
:
if
"min"
in
info
[
1
]
and
val
<
info
[
1
][
"min"
]:
if
"min"
in
info
[
1
]
and
val
<
info
[
1
][
"min"
]:
return
(
False
,
"Value {} smaller than min of {}. {}, {}"
.
format
(
val
,
info
[
1
][
"min"
],
class_type
,
x
),
unique_id
)
error
=
{
"type"
:
"value_smaller_than_min"
,
"message"
:
"Value {} smaller than min of {}"
.
format
(
val
,
info
[
1
][
"min"
]),
"details"
:
f
"
{
x
}
"
,
"extra_info"
:
{
"input_name"
:
x
,
"input_config"
:
info
,
"received_value"
:
val
,
}
}
errors
.
append
(
error
)
continue
if
"max"
in
info
[
1
]
and
val
>
info
[
1
][
"max"
]:
if
"max"
in
info
[
1
]
and
val
>
info
[
1
][
"max"
]:
return
(
False
,
"Value {} bigger than max of {}. {}, {}"
.
format
(
val
,
info
[
1
][
"max"
],
class_type
,
x
),
unique_id
)
error
=
{
"type"
:
"value_bigger_than_max"
,
"message"
:
"Value {} bigger than max of {}"
.
format
(
val
,
info
[
1
][
"max"
]),
"details"
:
f
"
{
x
}
"
,
"extra_info"
:
{
"input_name"
:
x
,
"input_config"
:
info
,
"received_value"
:
val
,
}
}
errors
.
append
(
error
)
continue
if
hasattr
(
obj_class
,
"VALIDATE_INPUTS"
):
if
hasattr
(
obj_class
,
"VALIDATE_INPUTS"
):
input_data_all
=
get_input_data
(
inputs
,
obj_class
,
unique_id
)
input_data_all
=
get_input_data
(
inputs
,
obj_class
,
unique_id
)
#ret = obj_class.VALIDATE_INPUTS(**input_data_all)
#ret = obj_class.VALIDATE_INPUTS(**input_data_all)
ret
=
map_node_over_list
(
obj_class
,
input_data_all
,
"VALIDATE_INPUTS"
)
ret
=
map_node_over_list
(
obj_class
,
input_data_all
,
"VALIDATE_INPUTS"
)
for
r
in
ret
:
for
i
,
r
in
enumerate
(
ret
):
if
r
!=
True
:
if
r
is
not
True
:
return
(
False
,
"{}, {}"
.
format
(
class_type
,
r
),
unique_id
)
details
=
f
"
{
x
}
"
if
r
is
not
False
:
details
+=
f
":
{
str
(
r
)
}
"
else
:
details
+=
"."
error
=
{
"type"
:
"custom_validation_failed"
,
"message"
:
"Custom validation failed for node"
,
"details"
:
details
,
"extra_info"
:
{
"input_name"
:
x
,
"input_config"
:
info
,
"received_value"
:
val
,
}
}
errors
.
append
(
error
)
continue
else
:
else
:
if
isinstance
(
type_input
,
list
):
if
isinstance
(
type_input
,
list
):
if
val
not
in
type_input
:
if
val
not
in
type_input
:
return
(
False
,
"Value not in list. {}, {}: {} not in {}"
.
format
(
class_type
,
x
,
val
,
type_input
),
unique_id
)
input_config
=
info
list_info
=
""
# Don't send back gigantic lists like if they're lots of
# scanned model filepaths
if
len
(
type_input
)
>
20
:
list_info
=
f
"(list of length
{
len
(
type_input
)
}
)"
input_config
=
None
else
:
list_info
=
str
(
type_input
)
error
=
{
"type"
:
"value_not_in_list"
,
"message"
:
"Value not in list"
,
"details"
:
f
"
{
x
}
: '
{
val
}
' not in
{
list_info
}
"
,
"extra_info"
:
{
"input_name"
:
x
,
"input_config"
:
input_config
,
"received_value"
:
val
,
}
}
errors
.
append
(
error
)
continue
if
len
(
errors
)
>
0
or
valid
is
not
True
:
ret
=
(
False
,
errors
,
unique_id
)
else
:
ret
=
(
True
,
[],
unique_id
)
ret
=
(
True
,
""
,
unique_id
)
validated
[
unique_id
]
=
ret
validated
[
unique_id
]
=
ret
return
ret
return
ret
def
full_type_name
(
klass
):
module
=
klass
.
__module__
if
module
==
'builtins'
:
return
klass
.
__qualname__
return
module
+
'.'
+
klass
.
__qualname__
def
validate_prompt
(
prompt
):
def
validate_prompt
(
prompt
):
outputs
=
set
()
outputs
=
set
()
for
x
in
prompt
:
for
x
in
prompt
:
...
@@ -356,7 +483,13 @@ def validate_prompt(prompt):
...
@@ -356,7 +483,13 @@ def validate_prompt(prompt):
outputs
.
add
(
x
)
outputs
.
add
(
x
)
if
len
(
outputs
)
==
0
:
if
len
(
outputs
)
==
0
:
return
(
False
,
"Prompt has no outputs"
,
[],
[])
error
=
{
"type"
:
"prompt_no_outputs"
,
"message"
:
"Prompt has no outputs"
,
"details"
:
""
,
"extra_info"
:
{}
}
return
(
False
,
error
,
[],
[])
good_outputs
=
set
()
good_outputs
=
set
()
errors
=
[]
errors
=
[]
...
@@ -364,34 +497,72 @@ def validate_prompt(prompt):
...
@@ -364,34 +497,72 @@ def validate_prompt(prompt):
validated
=
{}
validated
=
{}
for
o
in
outputs
:
for
o
in
outputs
:
valid
=
False
valid
=
False
reason
=
""
reason
s
=
[]
try
:
try
:
m
=
validate_inputs
(
prompt
,
o
,
validated
)
m
=
validate_inputs
(
prompt
,
o
,
validated
)
valid
=
m
[
0
]
valid
=
m
[
0
]
reason
=
m
[
1
]
reasons
=
m
[
1
]
node_id
=
m
[
2
]
except
Exception
as
ex
:
except
Exception
as
e
:
typ
,
_
,
tb
=
sys
.
exc_info
()
print
(
traceback
.
format_exc
())
valid
=
False
valid
=
False
reason
=
"Parsing error"
error_type
=
full_type_name
(
typ
)
node_id
=
None
reasons
=
[{
"type"
:
"exception_during_validation"
,
if
valid
==
True
:
"message"
:
"Exception when validating node"
,
"details"
:
str
(
ex
),
"extra_info"
:
{
"error_type"
:
error_type
,
"traceback"
:
traceback
.
format_tb
(
tb
)
}
}]
validated
[
o
]
=
(
False
,
reasons
,
o
)
if
valid
is
True
:
good_outputs
.
add
(
o
)
good_outputs
.
add
(
o
)
else
:
else
:
print
(
"Failed to validate prompt for output {} {}"
.
format
(
o
,
reason
))
print
(
f
"Failed to validate prompt for output
{
o
}
:"
)
print
(
"output will be ignored"
)
if
len
(
reasons
)
>
0
:
errors
+=
[(
o
,
reason
)]
print
(
"* (prompt):"
)
if
node_id
is
not
None
:
for
reason
in
reasons
:
if
node_id
not
in
node_errors
:
print
(
f
" -
{
reason
[
'message'
]
}
:
{
reason
[
'details'
]
}
"
)
node_errors
[
node_id
]
=
{
"message"
:
reason
,
"dependent_outputs"
:
[]}
errors
+=
[(
o
,
reasons
)]
node_errors
[
node_id
][
"dependent_outputs"
].
append
(
o
)
for
node_id
,
result
in
validated
.
items
():
valid
=
result
[
0
]
reasons
=
result
[
1
]
# If a node upstream has errors, the nodes downstream will also
# be reported as invalid, but there will be no errors attached.
# So don't return those nodes as having errors in the response.
if
valid
is
not
True
and
len
(
reasons
)
>
0
:
if
node_id
not
in
node_errors
:
class_type
=
prompt
[
node_id
][
'class_type'
]
node_errors
[
node_id
]
=
{
"errors"
:
reasons
,
"dependent_outputs"
:
[],
"class_type"
:
class_type
}
print
(
f
"*
{
class_type
}
{
node_id
}
:"
)
for
reason
in
reasons
:
print
(
f
" -
{
reason
[
'message'
]
}
:
{
reason
[
'details'
]
}
"
)
node_errors
[
node_id
][
"dependent_outputs"
].
append
(
o
)
print
(
"Output will be ignored"
)
if
len
(
good_outputs
)
==
0
:
if
len
(
good_outputs
)
==
0
:
errors_list
=
"
\n
"
.
join
(
set
(
map
(
lambda
a
:
"{}"
.
format
(
a
[
1
]),
errors
)))
errors_list
=
[]
return
(
False
,
"Prompt has no properly connected outputs
\n
{}"
.
format
(
errors_list
),
list
(
good_outputs
),
node_errors
)
for
o
,
errors
in
errors
:
for
error
in
errors
:
return
(
True
,
""
,
list
(
good_outputs
),
node_errors
)
errors_list
.
append
(
f
"
{
error
[
'message'
]
}
:
{
error
[
'details'
]
}
"
)
errors_list
=
"
\n
"
.
join
(
errors_list
)
error
=
{
"type"
:
"prompt_no_good_outputs"
,
"message"
:
"Prompt has no properly connected outputs"
,
"details"
:
errors_list
,
"extra_info"
:
{}
}
return
(
False
,
error
,
list
(
good_outputs
),
node_errors
)
return
(
True
,
None
,
list
(
good_outputs
),
node_errors
)
class
PromptQueue
:
class
PromptQueue
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment