1414 get_model_names_for_provider ,
1515 get_provider_from_variable_name ,
1616)
17- from langflow .services .auth import utils as auth_utils
1817from langflow .services .database .models .variable .model import VariableCreate , VariableRead , VariableUpdate
1918from langflow .services .deps import get_variable_service
2019from langflow .services .variable .constants import CREDENTIAL_TYPE , GENERIC_TYPE
@@ -151,15 +150,10 @@ async def read_variables(
151150):
152151 """Read all variables.
153152
154- Model provider credentials are validated when reading from the database.
155- If a provider key is invalid, its default_fields are cleared to prevent
156- the provider from appearing enabled.
153+ Model provider credentials are validated when they are created or updated,
154+ not on every read. This avoids latency from external API calls on read operations.
157155
158- Each variable in the response includes:
159- - is_valid: bool | None - True if valid, False if invalid, None if not a provider credential
160- - validation_error: str | None - Error message if validation failed
161-
162- Returns a list of variables with validation status for model provider credentials.
156+ Returns a list of variables.
163157 """
164158 variable_service = get_variable_service ()
165159 if not isinstance (variable_service , DatabaseVariableService ):
@@ -173,113 +167,18 @@ async def read_variables(
173167 var for var in all_variables if not (var .name and var .name .startswith ("__" ) and var .name .endswith ("__" ))
174168 ]
175169
176- # Validate model provider credentials and clear default_fields if invalid
177- # Build dict of credential variables for validation
178- credential_variables = {var .name : var for var in filtered_variables if var .type == CREDENTIAL_TYPE }
179- provider_variable_map = get_model_provider_variable_mapping ()
180-
181- # Create reverse mapping: variable_name -> provider
182- var_to_provider = {var_name : provider for provider , var_name in provider_variable_map .items ()}
183-
184- # Validate each provider credential once and capture both enabled status and error messages
185- validation_results : dict [
186- str , tuple [bool , str | None , list [str ] | None ]
187- ] = {} # var_name -> (is_valid, error, default_fields)
188-
189- for var_name in provider_variable_map .values ():
190- if var_name in credential_variables :
191- is_valid = False
192- error_message = None
193- variable_obj = None
194-
195- try :
196- # Get the raw Variable object to access the encrypted value
197- variable_obj = await variable_service .get_variable_object (
198- user_id = current_user .id , name = var_name , session = session
199- )
200- if variable_obj and variable_obj .value :
201- # Decrypt the API key value
202- from langflow .services .deps import get_settings_service
203-
204- settings_service = get_settings_service ()
205- decrypted_value = auth_utils .decrypt_api_key (
206- variable_obj .value , settings_service = settings_service
207- )
208- if decrypted_value and decrypted_value .strip ():
209- # Validate the key (this will raise ValueError if invalid)
210- await asyncio .to_thread (validate_model_provider_key , var_name , decrypted_value )
211- # Validation passed
212- is_valid = True
213- error_message = None
214- else :
215- error_message = "API key is empty"
216- else :
217- error_message = "Variable value is empty"
218- except ValueError as e :
219- # Validation failed - get the error message
220- error_message = str (e )
221- except Exception as e : # noqa: BLE001
222- error_message = f"Validation error: { e !s} "
223-
224- # Update default_fields based on validation result
225- updated_default_fields = None
226- if variable_obj and variable_obj .id :
227- try :
228- if is_valid :
229- # Key is valid - ensure default_fields are set (important for migration)
230- provider_name = var_to_provider .get (var_name )
231- expected_default_fields = [provider_name , "api_key" ] if provider_name else []
232- if variable_obj .default_fields != expected_default_fields :
233- await variable_service .update_variable_fields (
234- user_id = current_user .id ,
235- variable_id = variable_obj .id ,
236- variable = VariableUpdate (
237- id = variable_obj .id ,
238- default_fields = expected_default_fields ,
239- ),
240- session = session ,
241- )
242- updated_default_fields = expected_default_fields
243- else :
244- # Key is invalid - clear default_fields
245- if variable_obj .default_fields :
246- await variable_service .update_variable_fields (
247- user_id = current_user .id ,
248- variable_id = variable_obj .id ,
249- variable = VariableUpdate (
250- id = variable_obj .id ,
251- default_fields = [],
252- ),
253- session = session ,
254- )
255- updated_default_fields = []
256- except Exception : # noqa: BLE001
257- # Log but don't fail if we can't update
258- # Use current default_fields if update failed
259- updated_default_fields = variable_obj .default_fields if variable_obj else None
260-
261- validation_results [var_name ] = (is_valid , error_message , updated_default_fields )
262-
263- # Set validation status on each variable and update default_fields in response
170+ # Mark model provider credentials - validation status is based on existence
171+ # (actual validation happens on create/update)
264172 for var in filtered_variables :
265173 if var .name and var .name in model_provider_variable_mapping .values () and var .type == CREDENTIAL_TYPE :
266- result = validation_results .get (var .name )
267- if result :
268- is_valid , error_message , updated_default_fields = result
269- var .is_valid = is_valid
270- var .validation_error = error_message
271- # Update default_fields in response to reflect what we set in database
272- # This is important for migration - valid keys will have default_fields set
273- if updated_default_fields is not None :
274- var .default_fields = updated_default_fields
275- else :
276- # Variable not found in validation results
277- var .is_valid = False
278- var .validation_error = "Variable not found"
174+ # Credential exists and was validated on save
175+ var .is_valid = True
176+ var .validation_error = None
279177 else :
280- # Not a model provider credential, validation fields remain None
178+ # Not a model provider credential
281179 var .is_valid = None
282180 var .validation_error = None
181+
283182 except Exception as e :
284183 raise HTTPException (status_code = 500 , detail = str (e )) from e
285184 else :
0 commit comments