diff --git a/litellm/llms/vertex_ai/credentials_source.py b/litellm/llms/vertex_ai/credentials_source.py index a973d60d21c..31510a8981e 100644 --- a/litellm/llms/vertex_ai/credentials_source.py +++ b/litellm/llms/vertex_ai/credentials_source.py @@ -74,6 +74,9 @@ def _read_json_file(path: str) -> _VertexCredentialsFile: return VertexCredentialsFileUnreadable(path, f"{e.strerror or e} ({type(e).__name__})") except UnicodeDecodeError: return VertexCredentialsFileNotJson(path, "file is not UTF-8 text") + except ValueError as e: + # open() rejects a few paths before touching the filesystem, e.g. "embedded null byte". + return VertexCredentialsFileUnreadable(path, f"{e} ({type(e).__name__})") parsed: Final = _parse_json_object(contents) if isinstance(parsed, _NotAJsonObject): diff --git a/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py b/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py index d55901e79fe..6ef89fd8163 100644 --- a/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py +++ b/tests/test_litellm/llms/vertex_ai/test_vertex_llm_base.py @@ -2304,6 +2304,13 @@ class TestVertexCredentialsSource: assert project_id == "from-inline" assert from_sa.call_args.args[0] == {"type": "service_account", "project_id": "from-inline"} + def test_a_path_open_rejects_outright_is_reported_not_raised_raw(self): + """open() rejects some paths with a bare ValueError before any filesystem call.""" + with pytest.raises(ValueError, match="Unable to read the vertex credentials file") as exc_info: + VertexBase().load_auth(credentials="creds" + chr(0) + ".json", project_id="p") + + assert "embedded null" in str(exc_info.value) + def test_a_file_whose_name_starts_with_a_brace_is_still_read(self, tmp_path): """Shape dispatch must not strand a real file that happens to be named like JSON.""" braced = tmp_path / "{vertex}.json"