continuedev/continue · error · Error

Failed to make API call after ${maxTries} retries

Error message

Failed to make API call after ${maxTries} retries

What it means

Thrown by withExponentialBackoff when the wrapped API call still fails after exhausting all retry attempts (only retryable errors are retried; other errors re-throw immediately). It is a terminal wrapper error meaning the underlying failure persisted across every retry with exponential delay.

Source

Thrown at core/util/withExponentialBackoff.ts:41

      ) {
        const retryAfter = (error as APIError).response?.headers.get(
          RETRY_AFTER_HEADER,
        );
        const delay = retryAfter
          ? parseInt(retryAfter, 10)
          : initialDelaySeconds * 2 ** attempt;
        console.log(
          `Hit rate limit. Retrying in ${delay} seconds (attempt ${
            attempt + 1
          })`,
        );
        await new Promise((resolve) => setTimeout(resolve, delay * 1000));
      } else {
        throw error; // Re-throw other errors
      }
    }
  }
  throw new Error(`Failed to make API call after ${maxTries} retries`);
};

export { withExponentialBackoff };

View on GitHub (pinned to 5522c6f44c)

Solutions

  1. Inspect the underlying service/API the wrapped call hits and fix the root cause (auth, endpoint, payload)
  2. Increase maxTries and/or backoff delay for transient failures like rate limits
  3. Verify your retryable-error classifier inside the wrapper so permanent errors fail fast
  4. Add logging of each retry's error before the final throw

Example fix

// before
await withExponentialBackoff(() => api.call(), 3, 2);
// after
await withExponentialBackoff(() => api.call(), 5, 3); // more tries, longer backoff
Defensive patterns

Strategy: retry

Validate before calling

// Pre-check endpoint health / auth before wrapping
if (!(await api.healthCheck())) throw new Error('API unavailable');

Try / catch

try {
  await withExponentialBackoff(fn, 5, 2);
} catch (e) {
  if (e instanceof Error && e.message.includes('after') && e.message.includes('retries')) {
    // permanent failure after retries: alert / circuit-break
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling withExponentialBackoff(fn, ...) where fn keeps throwing retryable errors (e.g. HTTP 429/500, network timeouts) for all maxTries attempts. The original error is lost; only this generic message surfaces.

Common situations: API outage, rate limiting without sufficient backoff, invalid credentials causing repeated 401s being classified retryable, or maxTries set too low for a flaky endpoint.

Related errors


AI-assisted analysis of continuedev/continue@5522c6f44c (2026-08-27). Data as JSON: /api/errors/c4d65aca4711251b. Report an issue: GitHub.