@@ -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 = {
@@ -940,6 +977,34 @@ async def validate_inputs(prompt_id, prompt, item, validated):
940977 errors .append (error )
941978 continue
942979
980+ if input_type == "STRING" :
981+ if "minLength" in extra_info and len (val ) < extra_info ["minLength" ]:
982+ error = {
983+ "type" : "value_shorter_than_min_length" ,
984+ "message" : "Value length {} shorter than min length of {}" .format (len (val ), extra_info ["minLength" ]),
985+ "details" : f"{ x } " ,
986+ "extra_info" : {
987+ "input_name" : x ,
988+ "input_config" : info ,
989+ "received_value" : val ,
990+ }
991+ }
992+ errors .append (error )
993+ continue
994+ if "maxLength" in extra_info and len (val ) > extra_info ["maxLength" ]:
995+ error = {
996+ "type" : "value_longer_than_max_length" ,
997+ "message" : "Value length {} longer than max length of {}" .format (len (val ), extra_info ["maxLength" ]),
998+ "details" : f"{ x } " ,
999+ "extra_info" : {
1000+ "input_name" : x ,
1001+ "input_config" : info ,
1002+ "received_value" : val ,
1003+ }
1004+ }
1005+ errors .append (error )
1006+ continue
1007+
9431008 if isinstance (input_type , list ) or input_type == io .Combo .io_type :
9441009 if input_type == io .Combo .io_type :
9451010 combo_options = extra_info .get ("options" , [])
0 commit comments