Skip to content

fix: handle explicit outputInfo: null in Vertex AI batch response - #34097

Closed
htourinho-clgx wants to merge 3 commits into
BerriAI:litellm_oss_daily_2026_07_20from
htourinho-clgx:fix/vertex-batch-output-info-null
Closed

fix: handle explicit outputInfo: null in Vertex AI batch response#34097
htourinho-clgx wants to merge 3 commits into
BerriAI:litellm_oss_daily_2026_07_20from
htourinho-clgx:fix/vertex-batch-output-info-null

Conversation

@htourinho-clgx

@htourinho-clgx htourinho-clgx commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Relevant issues

litellm.create_batch() / retrieve_batch() against a Vertex AI-backed
model can raise an opaque openai.InternalServerError: 500 - "'NoneType' object has no attribute 'get'" if Vertex AI returns HTTP 200 with an
explicit "outputInfo": null body - the output directory is assigned
asynchronously by Vertex and is not always populated in the synchronous
response.

Correction (please read): an earlier version of this PR description
stated this was confirmed as a live incident in our own environment,
"with the exact vulnerable line ... present, unpatched, in the specific
litellm version pinned in that environment (1.83.10)". That claim was
based on a version pin in a dependency file, not on the actually deployed
proxy image. After checking the real running container version directly
(Helm/Kubernetes labels on the live pods, both in our dev and UAT
environments), the version actually deployed there is 1.72.2, which
predates this code path entirely (_get_output_file_id_from_vertex_ai_batch_response
in 1.72.2 doesn't reference outputInfo at all - it uses a different,
fully null-guarded outputConfig.gcsDestination path). The real incident
that triggered our investigation was therefore not this bug - it was a
separate, unrelated defect, which we've filed separately as
#34260.

Apologies for the earlier inaccurate evidence claim. The code defect this
PR fixes is still real and independently verified by direct source
inspection (see below) - we're just no longer claiming a live production
reproduction of this specific bug from our side, since we can't honestly
back that claim with our own incident.

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (5/5, "safe to merge, no blocking issues found")

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Found via direct source code review, not a live incident on our side:
confirmed the exact vulnerable, unguarded outputInfo.get(...) call is
present in litellm 1.83.10, 1.85.1, 1.92.0, and 1.93.0 by inspecting the
real published source of each version directly. We do not currently run
any of these versions in our own deployed environments, so we can't supply
a live before/after from production - the reproduction below uses the real
function from this PR's diff, called directly with the exact response
shape Vertex AI's own API is documented to allow.

At commit
090c2e1:

Before (pre-fix code):

>>> raw_response = {"outputInfo": None, "outputConfig": {"gcsDestination": {"outputUriPrefix": "gs://bucket/output/"}}}
>>> raw_response.get("outputInfo", OutputInfo()).get("gcsOutputDirectory", "")
AttributeError: 'NoneType' object has no attribute 'get'

dict.get(key, default) only substitutes default when the key is
absent, not when it's present but explicitly None - this is what crashes
whenever Vertex returns outputInfo: null.

After (this PR's code, same input):

>>> VertexAIBatchTransformation._get_output_file_id_from_vertex_ai_batch_response(raw_response)
'gs://bucket/output/predictions.jsonl'

No crash; falls through cleanly to the outputConfig-derived path.

Also covered by the 2 new regression tests in
tests/test_litellm/llms/vertex_ai/batches/test_transformation.py
(test_get_output_file_id_output_info_explicit_none_falls_through_to_output_config,
test_get_output_file_id_output_info_explicit_none_and_no_output_config),
confirmed passing alongside all 44 pre-existing tests in that file.

Type

🐛 Bug Fix

Changes

  • litellm/llms/vertex_ai/batches/transformation.py: guard outputInfo being
    explicitly None before calling .get() on it, matching the null-safe
    pattern already used by the sibling _get_input_file_id_from_vertex_ai_batch_response.
  • tests/test_litellm/llms/vertex_ai/batches/test_transformation.py: 2 new
    regression tests for outputInfo: null, with and without an outputConfig
    fallback available.

Final Attestation

  • The tests check the right things, including the edge cases, and
    regressions in the respective real-world customer use-cases are not
    possible after this PR

Note

Low Risk
Narrow null-handling fix in batch response mapping with targeted tests; dashboard dependency override bumps are routine.

Overview
Fixes a crash in _get_output_file_id_from_vertex_ai_batch_response when Vertex AI returns HTTP 200 with "outputInfo": null. The previous code used response.get("outputInfo", OutputInfo()).get(...), which does not substitute the default when the key is present but null, leading to AttributeError and a surfaced 500 from batch create/retrieve.

The change normalizes outputInfo with response.get("outputInfo") or OutputInfo() before reading gcsOutputDirectory, so parsing can fall through to outputConfig.gcsDestination when the async output directory is not set yet.

Two regression tests cover outputInfo: null with and without an outputConfig fallback. The dashboard package.json overrides bump js-yaml and brace-expansion (lockfile updated accordingly).

Reviewed by Cursor Bugbot for commit 2cbec23. Bugbot is set up for automated code reviews on this repo. Configure here.

Vertex AI can return HTTP 200 for a create_batch/get_batch call with an
explicit "outputInfo": null body (the output directory is assigned
asynchronously and may not be populated yet at response time).

_get_output_file_id_from_vertex_ai_batch_response did:

    response.get("outputInfo", OutputInfo()).get("gcsOutputDirectory", "")

dict.get(key, default) only substitutes default when the key is absent,
not when it is present but explicitly None, so this crashed with:

    AttributeError: 'NoneType' object has no attribute 'get'

surfaced to callers as an opaque openai.InternalServerError 500 from
litellm.create_batch()/retrieve_batch() for any Vertex AI batch job,
regardless of whether the job ultimately succeeds.

Fixed by guarding with `response.get("outputInfo") or OutputInfo()`,
matching the existing null-safe pattern already used by the sibling
_get_input_file_id_from_vertex_ai_batch_response for inputConfig. The
existing outputConfig fallback branch (a few lines below) already
handles this case correctly once it's reachable - it just never was.

Added 2 regression tests covering outputInfo: null with and without an
outputConfig fallback available.
@CLAassistant

CLAassistant commented Jul 21, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greptile-apps

greptile-apps Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes null handling in Vertex AI batch responses and updates dashboard dependencies. The main changes are:

  • Handles explicit outputInfo: null values and uses the existing output configuration fallback
  • Adds tests for null output information with and without a fallback location
  • Updates the js-yaml and brace-expansion dashboard overrides and lockfile

Confidence Score: 5/5

This looks safe to merge.

  • The explicit null response now follows the existing output configuration fallback.
  • Tests cover the response both with and without a fallback output location.
  • No blocking issues were found in the updated code.

Important Files Changed

Filename Overview
litellm/llms/vertex_ai/batches/transformation.py Normalizes null output information before reading the output directory, preserving the existing fallback behavior.
tests/test_litellm/llms/vertex_ai/batches/test_transformation.py Adds focused tests for explicit null output information with and without an output configuration.
ui/litellm-dashboard/package.json Updates the dashboard overrides for js-yaml and brace-expansion.
ui/litellm-dashboard/package-lock.json Records the updated dependency resolutions and optional bundled packages.

Reviews (2): Last reviewed commit: "chore(ui): bump brace-expansion and js-y..." | Re-trigger Greptile

@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codspeed-hq

codspeed-hq Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing htourinho-clgx:fix/vertex-batch-output-info-null (090c2e1) with main (5d4c4d0)

Open in CodSpeed

@htourinho-clgx htourinho-clgx changed the title Fix: Vertex AI batch response crashes with AttributeError on explicit outputInfo: null fix: handle explicit outputInfo: null in Vertex AI batch response Jul 21, 2026
@htourinho-clgx
htourinho-clgx changed the base branch from main to litellm_oss_daily_2026_07_20 July 21, 2026 12:22
htourinho-clgx and others added 2 commits July 21, 2026 14:24
Bumps transitive npm dev-dependencies flagged by the repo's osv-scan CI check
(unrelated to the Vertex AI batch fix in this PR, but needed for CI to pass):

- js-yaml 4.2.0 -> 4.3.0 (GHSA-52cp-r559-cp3m)
- brace-expansion 5.0.6 -> 5.0.7 (GHSA-3jxr-9vmj-r5cp)

Both pinned via the existing 'overrides' block in ui/litellm-dashboard/package.json
(js-yaml was already pinned there; added brace-expansion alongside it). No direct
dependency changes - only transitive resolution. Verified locally with the exact
osv-scanner command CI runs: 'No issues found'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mateo-berri

Copy link
Copy Markdown
Contributor

@greptileai

@mateo-berri

Copy link
Copy Markdown
Contributor

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2cbec23. Configure here.

@mateo-berri

Copy link
Copy Markdown
Contributor

This has been merged into staging with a copy branch #34473. Thank you for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants