@@ -215,6 +215,41 @@ def mark_missing():
215215 v3_data ["hidden_inputs" ] = hidden_inputs_v3
216216 return input_data_all , missing_keys , v3_data
217217
218+ def validate_resolved_inputs (input_data_all , class_def , inputs ):
219+ """Validate resolved input values against schema constraints.
220+
221+ This is needed because validate_inputs() only sees direct widget values.
222+ Linked inputs aren't resolved during validate_inputs(), so this runs after resolution to catch any violations.
223+ """
224+ is_v3 = issubclass (class_def , _ComfyNodeInternal )
225+ valid_inputs = class_def .INPUT_TYPES ()
226+ if is_v3 :
227+ valid_inputs , _ , _ = _io .get_finalized_class_inputs (valid_inputs , inputs )
228+
229+ for x , values in input_data_all .items ():
230+ input_type , input_category , extra_info = get_input_info (class_def , x , valid_inputs )
231+ if extra_info is None :
232+ continue
233+ if input_type != "STRING" :
234+ continue
235+ min_length = extra_info .get ("minLength" )
236+ max_length = extra_info .get ("maxLength" )
237+ if min_length is None and max_length is None :
238+ continue
239+ for val in values :
240+ if val is None or not isinstance (val , str ):
241+ continue
242+ if min_length is not None and len (val ) < min_length :
243+ raise ValueError (
244+ f"Input '{ x } ': value length { len (val )} is shorter than "
245+ f"minimum length of { min_length } "
246+ )
247+ if max_length is not None and len (val ) > max_length :
248+ raise ValueError (
249+ f"Input '{ x } ': value length { len (val )} is longer than "
250+ f"maximum length of { max_length } "
251+ )
252+
218253map_node_over_list = None #Don't hook this please
219254
220255async def resolve_map_node_over_list_results (results ):
@@ -498,6 +533,8 @@ async def execute(server, dynprompt, caches, current_item, extra_data, executed,
498533 execution_list .make_input_strong_link (unique_id , i )
499534 return (ExecutionResult .PENDING , None , None )
500535
536+ validate_resolved_inputs (input_data_all , class_def , inputs )
537+
501538 def execution_block_cb (block ):
502539 if block .message is not None :
503540 mes = {
@@ -938,6 +975,34 @@ async def validate_inputs(prompt_id, prompt, item, validated):
938975 errors .append (error )
939976 continue
940977
978+ if input_type == "STRING" :
979+ if "minLength" in extra_info and len (val ) < extra_info ["minLength" ]:
980+ error = {
981+ "type" : "value_shorter_than_min_length" ,
982+ "message" : "Value length {} shorter than min length of {}" .format (len (val ), extra_info ["minLength" ]),
983+ "details" : f"{ x } " ,
984+ "extra_info" : {
985+ "input_name" : x ,
986+ "input_config" : info ,
987+ "received_value" : val ,
988+ }
989+ }
990+ errors .append (error )
991+ continue
992+ if "maxLength" in extra_info and len (val ) > extra_info ["maxLength" ]:
993+ error = {
994+ "type" : "value_longer_than_max_length" ,
995+ "message" : "Value length {} longer than max length of {}" .format (len (val ), extra_info ["maxLength" ]),
996+ "details" : f"{ x } " ,
997+ "extra_info" : {
998+ "input_name" : x ,
999+ "input_config" : info ,
1000+ "received_value" : val ,
1001+ }
1002+ }
1003+ errors .append (error )
1004+ continue
1005+
9411006 if isinstance (input_type , list ) or input_type == io .Combo .io_type :
9421007 if input_type == io .Combo .io_type :
9431008 combo_options = extra_info .get ("options" , [])
0 commit comments