@@ -119,8 +119,10 @@ impl ServerConfig {
119119 . map ( |name| ( name. clone ( ) , Vec :: new ( ) ) )
120120 . collect :: < BTreeMap < String , Vec < ModelConfig > > > ( ) ;
121121
122- for name in self . llm_clients . keys ( ) {
122+ // Validate every declared client even when no target currently references it.
123+ for ( name, client_config) in & self . llm_clients {
123124 validate_value ( "llm client name" , name) ?;
125+ build_backend ( name, client_config, & BTreeMap :: new ( ) ) ?;
124126 }
125127 for ( target_name, target) in & self . targets {
126128 let client_config = self . llm_clients . get ( & target. llm_client ) . ok_or_else ( || {
@@ -1132,6 +1134,21 @@ target = "weak"
11321134 }
11331135 }
11341136
1137+ #[ test]
1138+ fn rejects_invalid_unreferenced_llm_client ( ) {
1139+ let invalid = format ! (
1140+ "{VALID_CONFIG}\n \
1141+ [llm_clients.unused]\n \
1142+ format = \" openai_chat\" \n \
1143+ base_url = \" not a url\" \n "
1144+ ) ;
1145+ let message = error_message ( & invalid) ;
1146+ assert ! (
1147+ message. contains( "llm client unused base_url" ) ,
1148+ "unexpected error: {message}"
1149+ ) ;
1150+ }
1151+
11351152 #[ test]
11361153 fn an_escalation_table_switches_the_classifier_route_to_escalation ( ) -> ServerResult < ( ) > {
11371154 // Present: the classifier target judges the weak tier's reply each turn instead of
0 commit comments