Meta LLaMA batch inference failures after intermittent cloud API timeouts

Problem: Meta LLaMA Batch Inference Fails After Intermittent Cloud API Timeouts

In a production pipeline that runs large‑scale batch inference on Meta LLaMA, jobs started to abort after a few hundred input files were processed. The failure manifested as unhandled exceptions during both the input fetch phase (cloud storage read) and the result upload phase (cloud storage write). The symptoms were identical across AWS, GCP, and Azure deployments, indicating a cloud‑provider‑API‑related issue rather than a model bug.

Typical Error Messages

  • ReadTimeoutError: HTTP request timed out while fetching input file from S3
  • botocore.exceptions.EndpointConnectionError: Could not connect to the endpoint URL: "https://s3.amazonaws.com/..."
  • google.api_core.exceptions.DeadlineExceeded: 504 request timeout during GCS read/write operation
  • azure.core.exceptions.ServiceRequestError: The request failed with status code 500 – Internal Server Error
  • ConnectionResetError: [Errno 104] Connection reset by peer during result upload to cloud storage

Logs from a failed AWS run (excerpt):


2024-09-12 03:14:27,842 ERROR batch_inference.py:112 - ReadTimeoutError: HTTP request timed out while fetching input file from S3 (bucket=my-llama-input, key=doc_00457.txt)
2024-09-12 03:14:28,001 INFO  retry.py:45 - Retrying request (attempt 3/5) after 2.0 seconds
2024-09-12 03:14:30,213 ERROR batch_inference.py:215 - ServiceRequestError: The request failed with status code 500 – Internal Server Error (container=my-llama-output, blob=out_00457.json)
2024-09-12 03:14:30,214 CRITICAL batch_job.py:78 - Batch job aborted after 5 retries

Root Cause Analysis

The failures stem from three intertwined factors:

  1. Transient API throttling and service disruptions – Large‑scale ListObjectsV2 or manifest‑loading calls can exceed provider rate limits, causing 503/500 responses (see the AWS S3 throttling incident in the evidence package).
  2. Insufficient client‑side timeout and retry configuration – The default SDK timeouts (30 s for GCP, 60 s for AWS) are shorter than the latency observed in cross‑region or preemptible VM scenarios. The default retry policy (max 3 attempts) expires before the service recovers, leading to aborts.
  3. Batch job orchestration assumes atomicity of each file operation – The LLaMA inference script (as described in the official Distributed Inference Documentation) processes one input file at a time and aborts the entire job on any exception, amplifying the impact of a single transient error.

In short, the pipeline treats a temporary cloud API failure as fatal because the SDK settings are not tuned for high‑throughput, long‑running batch workloads.

Investigation and Debugging Steps

1. Capture SDK Metrics and Raw HTTP Traces

# AWS (botocore) – enable debug logging
export AWS_DEBUG=1
python batch_inference.py 2>&1 | tee batch_debug.log

Search the log for HTTP/1.1 503 Service Unavailable or ReadTimeoutError. The presence of repeated 503/500 status codes confirms provider throttling.

2. Verify Network Path and Latency

# Measure round‑trip time to storage endpoint
curl -w "\n%{time_total}\n" -o /dev/null -s https://storage.googleapis.com/my-bucket/

If the total time consistently exceeds 30 seconds, the default timeout will trigger.

3. Inspect Cloud Provider Metrics

  • AWS CloudWatch – 4xxErrorRate and 5xxErrorRate for the S3 bucket.
  • GCP Operations Suite – storage.googleapis.com/request_latencies.
  • Azure Monitor – BlobServiceRequests with ServerError status.

Spikes in these metrics correlate with the timestamps of the batch failures.

4. Reproduce with a Minimal Script

import boto3, botocore
s3 = boto3.client('s3', config=botocore.client.Config(
    connect_timeout=10,
    read_timeout=20,
    retries={'max_attempts': 3}
))
try:
    obj = s3.get_object(Bucket='my-llama-input', Key='doc_00457.txt')
    print(obj['Body'].read()[:100])
except Exception as e:
    print('Error:', e)

Running this against the same bucket reproduces the timeout within seconds, confirming that the SDK defaults are insufficient.

Resolution

1. Tune SDK Timeouts and Retry Policies

For each provider, configure a longer timeout (e.g., 300 s) and an exponential backoff with a higher max attempt count.

# AWS – botocore config
import botocore
s3 = boto3.client('s3', config=botocore.client.Config(
    connect_timeout=30,
    read_timeout=300,
    retries={
        'max_attempts': 10,
        'mode': 'standard'  # uses exponential backoff
    }
))
# GCP – google-cloud-storage client
from google.cloud import storage
client = storage.Client(
    client_options={'api_endpoint': 'https://storage.googleapis.com'},
    timeout=300  # seconds
)
# Azure – azure-storage-blob client
from azure.storage.blob import BlobServiceClient, RetryPolicy
retry = RetryPolicy(total_retries=10, backoff_factor=2, retry_mode='exponential')
blob_service = BlobServiceClient(account_url="https://myaccount.blob.core.windows.net", retry_policy=retry)

2. Batch‑Level Error Isolation

Modify the inference loop to catch per‑file exceptions, log them, and continue processing other files. At the end, write a manifest of failed items for later reprocessing.

failed = []
for key in input_manifest:
    try:
        text = fetch_input(key)               # uses tuned client
        output = run_llama_inference(text)    # LLaMA inference call
        upload_output(key, output)            # uses tuned client
    except Exception as exc:
        logger.error(f'File {key} failed: {exc}')
        failed.append(key)

if failed:
    with open('failed_manifest.json', 'w') as f:
        json.dump(failed, f)
    logger.info(f'{len(failed)} files failed; see failed_manifest.json')

3. Throttle List Operations and Use Pagination

When loading a manifest, replace a single massive ListObjectsV2 call with paginated requests and a small MaxKeys value (e.g., 1000). Insert a short sleep between pages to stay under the provider’s request‑rate limits.

paginator = s3.get_paginator('list_objects_v2')
for page in paginator.paginate(Bucket='my-llama-input', MaxKeys=1000):
    for obj in page.get('Contents', []):
        input_keys.append(obj['Key'])
    time.sleep(0.2)  # 5 req/s limit mitigation

Before vs. After Comparison

Aspect Before After
SDK read timeout 60 s (AWS), 30 s (GCP) 300 s
Retry attempts 3 10 with exponential backoff
Batch error handling Abort on first exception Log & continue, manifest of failures
ListObjectsV2 usage Single massive call Paginated calls with rate‑limit sleep

Verification

  1. Run a controlled batch of 10 000 files and monitor the job duration. Expect no fatal aborts.
  2. Check the logs for the absence of ReadTimeoutError, EndpointConnectionError, or ServiceRequestError after the first 5 minutes.
  3. Validate that failed_manifest.json is empty (or contains only items that truly failed due to data corruption).
  4. Inspect cloud provider metrics: error rates should stay below 0.1 % during the run.
  5. Run a health‑check endpoint that reads a random input file and writes a dummy output; ensure it completes within the configured timeout.

Prevention and Operational Guardrails

  • Monitoring: Create alerts on storage SDK error metrics (e.g., S3 5xxErrorRate > 0.5%) and on the size of failed_manifest.json after each batch.
  • Circuit Breaker: Wrap storage calls in a circuit‑breaker library (e.g., pybreaker) to pause the pipeline when error rates spike, allowing the provider to recover.
  • Capacity Planning: Align the number of concurrent VM workers with the storage service’s request‑per‑second limits. Use provider‑specific quotas APIs to verify limits.
  • Cross‑Region Latency Awareness: Prefer colocating VMs and storage in the same region; if cross‑region is required, increase the timeout proportionally (e.g., 2 × round‑trip latency).
  • Idempotent Uploads: Use if-generation-match (GCS) or If-Match (S3) headers to make uploads safe for retries.

Related Topic Hub: LLM Systems Troubleshooting Hub

FAQ

  1. Why do timeouts only appear after processing a few hundred files?
    The SDK reuses HTTP connections. After a burst of requests, the provider’s rate‑limit bucket depletes, causing throttling responses that manifest as timeouts once the connection pool reaches its limit.
  2. Can increasing the instance type (CPU/GPU) solve the problem?
    No. The bottleneck is the storage API, not compute. Larger instances only increase request concurrency, potentially worsening throttling unless the SDK limits are also adjusted.
  3. Do I need to modify the LLaMA model code?
    No. The issue is external to the model. The inference code can remain unchanged; only the storage client configuration and batch orchestration need updates.
  4. How should I handle partial output files left on the bucket after a failure?
    Use a deterministic naming scheme (e.g., output_{key}.json.tmp) and rename to the final name only after a successful upload. A cleanup job can purge *.tmp older than a threshold.
  5. What is the recommended backoff strategy for cloud storage retries?
    Exponential backoff with jitter (e.g., base=2 s, max=120 s, jitter=0‑0.5 × base) and a maximum of 10 attempts balances latency with recovery chances.