From 46968480c4eb26f0dcccf6d548a16afa08e42777 Mon Sep 17 00:00:00 2001 From: Vasilisa Parshikova Date: Thu, 5 Mar 2026 18:26:35 +0400 Subject: [PATCH] (sap) fix after bot review --- docs/my-website/docs/providers/sap.md | 17 +++++++++++++---- litellm/llms/sap/credentials.py | 11 ++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/docs/my-website/docs/providers/sap.md b/docs/my-website/docs/providers/sap.md index 8c76aca5af9..c796fff8b25 100644 --- a/docs/my-website/docs/providers/sap.md +++ b/docs/my-website/docs/providers/sap.md @@ -55,11 +55,20 @@ pip install litellm ``` ### Step 2: Set Your Credentials + + Choose **one** of these authentication methods: + +> **Breaking change**: credential resolution is "first-source-wins" +> +> Credential resolution no longer merges individual fields across sources. +> +> Resolution order is: +`kwargs` → `service key` → `env (AICORE_*)` → `config` → `VCAP service` +> +> **Important behavior:** once LiteLLM finds *any* credential value in a source, it takes **all** credentials from that source exclusively (except `resource_group`, which may still be resolved separately). -Choose **one** of these authentication methods: - - - + + The simplest approach - paste your entire service key as a single environment variable. The service key must be wrapped in a `credentials` object: diff --git a/litellm/llms/sap/credentials.py b/litellm/llms/sap/credentials.py index 065d12e577b..56777a6ff19 100644 --- a/litellm/llms/sap/credentials.py +++ b/litellm/llms/sap/credentials.py @@ -62,7 +62,10 @@ def _load_json_env(var_name: str) -> Optional[Dict[str, Any]]: return None def _str_or_none(value) -> Optional[str]: - return str(value) if value is not None else None + try: + return str(value) if value is not None else None + except Exception: + return None def _load_vcap() -> Dict[str, Any]: @@ -220,14 +223,16 @@ def fetch_credentials(service_key: Optional[Union[str, dict]] = None, profile: O Source("kwargs", lambda cv: _str_or_none(kwargs.get(cv.name))), Source("service key", - lambda cv: _get_nested(service_key, cv.vcap_key if cv.vcap_key else (cv.name,)) + lambda cv: _str_or_none(_get_nested(service_key, cv.vcap_key if cv.vcap_key else (cv.name,))) if service_key else None), # type: ignore[arg-type] Source("environment variables", lambda cv: _str_or_none(os.environ.get(f'AICORE_{cv.name.upper()}'))), Source("config file", lambda cv: _str_or_none(config.get(f'AICORE_{cv.name.upper()}') or config.get(cv.name))), Source("VCAP service", - lambda cv: _get_nested(vcap_service, (("credentials",) + cv.vcap_key) if cv.vcap_key else (cv.name,)) + lambda cv: _str_or_none( + _get_nested(vcap_service, (("credentials",) + cv.vcap_key) if cv.vcap_key else (cv.name,)) + ) if vcap_service else None), # type: ignore[arg-type] ]