# Fix the translation agent loop retrying a failed Crowdin upload

## TL;DR

The agent retries forever because it never distinguishes retryable from fatal errors, so cap the retries and classify the error. A 401 retried 200 times is a loop, not resilience. Retry only transient errors, at most a few times, then stop and report.

## The error

```text
Translation agent log: retrying Crowdin upload, attempt 147
the API returns 401 every time, the agent never stops
```

## Fix it

### Step 1: Stop the runaway agent

```bash
pkill -f translate-agent || true
```

Expected: The loop stops.

### Step 2: Check what the API actually returns

```bash
curl -s -o /dev/null -w "%{http_code}" -H "your auth header https://api.crowdin.com/api/v2/user
```

Expected: You see the real status, likely 401.

### Step 3: Add a retry cap and error classification

```bash
node -e "console.log('max 3 retries, only on 429/5xx/network errors, everything else fails immediately')"
```

Expected: Fatal errors stop the loop on the first try.

### Step 4: Fix the underlying 401, then rerun

```bash
node -e "console.log('refresh the credential, then run the agent -- it should fail fast or succeed, never loop')"
```

Expected: The agent completes or errors cleanly.

## When to use this

- A translation agent loops retrying a failed upload
- Retry counts climb into the hundreds

## When NOT to use this

- Retries are bounded and eventually succeed, that is working as designed
- The loop is in extraction, different fix

## Tool and version compatibility

- Any agent with upload retry logic
- Crowdin API v2 error codes

## Variant phrasings

### loop on 429 without honoring retry-after

Bounded retries plus honoring retry-after. The cap alone still hammers the API.

### loop across restarts, not within one run

The checkpoint says incomplete so it restarts forever. Fix the root error, then clear the poisoned state.

## Why it happens

Unbounded retry with no error classification treats a permanent 401 like a transient blip. Each attempt fails identically, the agent tries again, and the loop runs until someone kills it, burning API quota the whole time.

## Edge cases

- Alert on final failure, a capped retry that always fails is still a bug
- Exponential backoff without a cap is still unbounded, cap the count too
- Log the error body on final failure, the classification depends on it

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_V0YLHBDkvs64oqDMxWFDEA
