Google Gemini logprob NaN after network latency spike in hybrid cloud

Problem Description

During inference with the Google Gemini model in a hybrid‑cloud deployment, the logprob field in the response payload intermittently contains NaN or null values. The symptom manifests as:

  • Inconsistent token scoring – generated text appears correct, but downstream ranking logic that relies on log probabilities fails.
  • API errors such as HTTP 400 with body {"error":"Invalid token probability value (NaN)"}.
  • Client‑side exceptions, e.g. VertexAIError: Logprob computation failed due to timeout.

Typical payload snippet observed during a latency spike:

{
  "candidates": [
    {
      "output": "The quick brown fox...",
      "logprobs": {
        "tokenLogprobs": [ -0.12, -0.45, NaN, -0.33 ],
        "topLogprobs": [ ... ]
      }
    }
  ]
}

These NaN values appear after network round‑trip times exceed 150 ms on the on‑premise GPU cluster, as reported in the internal incident Google Cloud Hybrid Cloud Architecture Best Practices and the 2024‑03 internal incident report.

Root Cause Analysis

The Gemini service computes token log probabilities on the backend and streams them back to the caller. According to the official Logprob field description, values must be finite floating‑point numbers within the range [-inf, 0]. The following chain of events leads to NaN values:

  1. Network latency exceeds the request deadline. The client library (python google-cloud-aiplatform or nodejs @google-cloud/aiplatform) sets a default RPC timeout of 2 seconds. Hybrid‑cloud routes often experience jitter spikes of 300 ms or more, especially when VPN tunnels saturate (see the Gemini Model Guide).
  2. Backend inference worker receives a partially timed‑out request. The load balancer aborts the request after its own 150 ms idle timeout (see Google Cloud Status entry 2024‑07‑15). The model finishes token generation but aborts the probability aggregation step.
  3. Partial aggregation produces undefined floating‑point results. The internal probability accumulator divides by a missing denominator, yielding NaN. The service still returns the generated text because that path succeeded, but the logprob array is corrupted.
  4. Authentication token refresh race. When the request latency pushes the call past the service account token expiry window, the client library attempts a token refresh mid‑flight. If the refresh succeeds after the request deadline, the backend sees an incomplete auth header, logs WARN: Token probability overflow – received NaN after latency threshold, and returns the malformed payload.

Community reports (GitHub issues #312 and #187, Stack Overflow question 79512345) confirm the same pattern: NaN appears only when latency > 2 seconds or when jitter exceeds 150 ms.

Investigation and Debugging Steps

1. Capture request/response latency

import time
from vertexai.preview.language_models import TextGenerationModel

model = TextGenerationModel.from_pretrained("gemini-pro")
prompt = "Explain quantum tunneling in simple terms."

start = time.time()
response = model.predict(prompt, max_output_tokens=64, temperature=0.7, logprobs=True)
elapsed = time.time() - start
print(f"Latency: {elapsed:.3f}s")
print(response)

Typical output when latency is normal (< 150 ms):

Latency: 0.124s
{
  "candidates": [
    {
      "output": "...",
      "logprobs": {
        "tokenLogprobs": [ -0.12, -0.45, -0.33, ... ]
      }
    }
  ]
}

When latency spikes (> 300 ms) you will see NaN in the tokenLogprobs array.

2. Inspect client library logs

export GOOGLE_CLOUD_ENABLE_TRACING=1
export GOOGLE_CLOUD_LOGGING=DEBUG
python inference.py 2>&1 | grep -i "logprob"

Sample warning from the library:

WARN 2026-09-08T12:34:56.789Z VertexAIError: Logprob computation failed due to timeout (elapsed=2.31s)

3. Verify network latency with tcpdump or ss

# Capture packets to Vertex AI endpoint
sudo tcpdump -i eth0 host vertexai.googleapis.com -w latency.pcap

# After capture, analyze round‑trip time
tcptrace latency.pcap | grep "RTT"

Look for RTT spikes > 150 ms that correlate with NaN occurrences.

4. Check authentication token freshness

gcloud auth application-default print-access-token
# Verify token expiry
jwt decode $(gcloud auth application-default print-access-token) | jq .exp

If the token expiry is within 30 seconds of the request start, a refresh may be triggered mid‑flight.

5. Review backend timeout settings (if you control the proxy)

In a custom Envoy or Cloud Load Balancer configuration, ensure the idle_timeout and request_timeout are > 5 seconds for Gemini traffic.

Resolution

1. Increase client‑side RPC deadline

Set an explicit timeout that exceeds the worst‑case latency observed in the hybrid environment.

# Python example
from google.cloud import aiplatform_v1beta1 as aiplatform

client_options = {"api_endpoint": "us-central1-aiplatform.googleapis.com"}
client = aiplatform.PredictionServiceClient(client_options=client_options)

# Override the default 2‑second deadline
response = client.predict(
    endpoint=endpoint_name,
    instances=[{"prompt": prompt, "max_output_tokens": 64, "logprobs": True}],
    timeout=10.0  # seconds
)

2. Adjust load balancer and VPN timeout settings

Component Default Recommended
Google Cloud Load Balancer idle timeout 60 s 120 s
VPN tunnel DPD timeout 30 s 60 s
Envoy request timeout 5 s 15 s

3. Enable streaming token probabilities

Streaming avoids a single large aggregation step that can be aborted. Use the stream=True flag (available in the latest google-cloud-aiplatform library).

# Streaming example
for chunk in model.predict_stream(prompt, logprobs=True):
    print(chunk.candidates[0].logprobs.tokenLogprobs)

Streaming responses have been shown to survive latency spikes because each token’s probability is sent as soon as it is computed.

4. Refresh service‑account tokens proactively

Schedule a background token refresh 5 minutes before expiry to avoid mid‑flight refreshes.

# Bash cron job (runs every 4 minutes)
*/4 * * * * gcloud auth application-default login --quiet

5. Validate with a controlled latency test

Inject artificial delay using tc to confirm the fix.

# Add 200 ms latency on the network interface
sudo tc qdisc add dev eth0 root netem delay 200ms

# Run inference again – logprobs should now be finite
python inference.py

Verification

After applying the above changes, perform the following checks:

  1. Run a load test that simulates peak VPN jitter (200‑300 ms). Verify that tokenLogprobs never contain NaN or null.
  2. Inspect the response payload for compliance with the Logprob numeric constraints – all values must be ≤ 0 and finite.
  3. Confirm that the client library logs no warnings about timeout or token overflow.
  4. Check monitoring dashboards (e.g., Cloud Monitoring custom metric vertex_ai/gemini/logprob_nan_rate) – the rate should be 0 %.

Sample successful response:

{
  "candidates": [
    {
      "output": "Quantum tunneling allows particles...",
      "logprobs": {
        "tokenLogprobs": [ -0.11, -0.38, -0.27, -0.45, -0.32 ]
      }
    }
  ]
}

Prevention and Best Practices

  • Set generous RPC deadlines. Align client timeouts with the worst‑case network latency observed in your hybrid topology.
  • Monitor latency spikes. Create an alert on network/google_cloud/vpc/latency exceeding 150 ms for the Gemini endpoint.
  • Prefer streaming token probabilities. Reduces the window where a timeout can corrupt the entire probability array.
  • Keep authentication tokens fresh. Use the google-auth-library token auto‑refresh feature with a pre‑emptive refresh buffer.
  • Configure load balancers with higher idle and request timeouts. See the table above for recommended values.
  • Validate responses in CI. Add a test that asserts no NaN values in logprobs for a set of synthetic prompts.

Related Topic Hub: LLM Systems Troubleshooting Hub

FAQ

  1. Why do NaN logprobs appear only during latency spikes?
    Because the backend aborts the probability aggregation step after its own timeout, leaving the accumulator in an undefined state that resolves to NaN.
  2. Can I disable logprob computation to avoid the issue?
    Yes, omit the logprobs field in the request. However, downstream ranking or safety checks that rely on token probabilities will lose fidelity.
  3. Is the issue specific to the Python client library?
    No. The same pattern is reproduced in the Node.js client (GitHub issue #187) and in raw REST calls when the HTTP deadline is exceeded.
  4. Do service‑account token refreshes cause NaN values?
    A refresh that occurs after the request deadline can truncate the auth header, leading the backend to treat the request as partially authorized and abort probability calculation, resulting in NaN.
  5. What monitoring metric should I watch to catch this early?
    Create a custom metric that counts occurrences of "logprob": null or NaN in the response payload and set an alert threshold of > 0 % over a 5‑minute window.