
OpenRouter 429 "Provider Returned Error" 해결 방법: 속도 제한, 업스트림 공급자, 폴백 옵션

이 두 오류는 로그에서 비슷하게 보이지만 근본 원인이 다릅니다:
- 429 Too Many Requests: 속도 제한에 도달하여 요청이 거부됨
- Provider returned error: OpenRouter는 요청을 수락했지만 업스트림 모델 공급자(OpenAI, Anthropic, Google 등)가 오류를 반환함
이 둘을 혼동하면 잘못된 해결책을 적용하게 됩니다. 이 가이드는 원인을 분리하고 올바른 대응 방법을 선택하는 데 도움을 드립니다.
요약
- OpenRouter 자체에서 발생한 429는 OpenRouter의 속도 제한 또는 할당량에 도달했다는 의미입니다.
- "provider returned error"는 업스트림 공급자가 요청을 거부했다는 의미이며, OpenRouter가 아닙니다.
- 응답 헤더와 오류 본문을 확인하여 둘을 구분하세요.
- 해결 방법이 다릅니다: OpenRouter 429는 키/티어 변경이 필요하고, 공급자 오류는 업스트림 진단이나 라우트 변경이 필요합니다.
- 프로덕션 워크로드의 경우, 오류가 발생하기 전에 폴백을 설계하세요.
1단계: 오류 응답을 주의 깊게 읽기
오류를 받으면 다음 세 가지를 확인하세요:
| 신호 | 확인 위치 | 알 수 있는 정보 |
|---|---|---|
| HTTP 상태 코드 | 응답 상태 | 429 = 속도 제한; 502/503 = 업스트림 장애 |
| 오류 메시지 본문 | JSON 응답의 error.message | "provider returned error"이거나 특정 속도 제한 메시지가 표시되는 경우가 많음 |
| 응답 헤더 | x-ratelimit-remaining, retry-after | OpenRouter 자체가 스로틀링하고 있는지 여부 |
일반적인 OpenRouter 429는 다음과 같습니다:
{
"error": {
"code": 429,
"message": "Rate limit exceeded. Please slow down."
}
}일반적인 공급자 오류는 다르게 보입니다:
{
"error": {
"code": 502,
"message": "Provider returned error: [upstream error details]"
}
}해결 방법이 다르므로 이 구분이 중요합니다.
2단계: 오류 원인 파악
다음 의사결정 트리를 사용하세요:
요청 실패
├── HTTP 429 + OpenRouter 속도 제한 메시지
│ → 원인: OpenRouter 수준의 속도 제한
│ → 해결: 요청 빈도 줄이기, 티어 업그레이드, 또는 지연 추가
│
├── HTTP 429 + 메시지에 "provider returned error"
│ → 원인: 업스트림 공급자 속도 제한이 전달됨
│ → 해결: 공급자 할당량 확인, 모델 변경, 또는 폴백 라우트 추가
│
├── HTTP 502/503 + "provider returned error"
│ → 원인: 업스트림 공급자 장애 또는 일시적 오류
│ → 해결: 백오프로 재시도, 공급자 변경, 또는 폴백 사용
│
└── HTTP 400/401 + 오류 메시지
→ 원인: 잘못된 요청, 유효하지 않은 키, 또는 모델을 찾을 수 없음
→ 해결: API 키, 모델 ID, 요청 형식 확인3단계: OpenRouter 수준의 429 해결
429가 OpenRouter 자체에서 발생한 경우(공급자에서 전달된 것이 아닌 경우), 다음을 순서대로 확인하세요:
3.1 현재 속도 제한 티어 확인
OpenRouter는 계정 티어에 따라 속도 제한을 적용합니다. 무료 티어 사용자는 유료 사용자보다 제한이 훨씬 낮습니다.
3.2 요청 빈도 줄이기
티어가 허용하는 것보다 빠르게 요청을 보내고 있다면:
import asyncio
import random
async def call_with_backoff(make_request, max_retries=5):
for attempt in range(max_retries):
try:
return await make_request()
except Exception as e:
if "429" in str(e) and attempt < max_retries - 1:
# Respect retry-after if present, otherwise use jittered backoff
delay = min(30, (2 ** attempt) + random.random())
await asyncio.sleep(delay)
else:
raise3.3 트래픽을 시간에 걸쳐 분산
에이전트 워크로드는 종종 버스트 패턴을 만듭니다. 50개의 요청을 동시에 보내는 대신:
- 세마포어로 동시 실행 수를 제한하세요
- 배치 사이에 작은 지연을 추가하세요
- 포그라운드와 백그라운드 큐를 분리하세요
4단계: 업스트림 공급자 오류 해결
오류 메시지에 "provider returned error"가 포함되어 있다면, 문제는 업스트림에 있습니다. OpenRouter가 요청을 전달했지만 모델 공급자가 거부한 것입니다.
4.1 일반적인 업스트림 원인
| 업스트림 원인 | 보이는 증상 | 확인 방법 |
|---|---|---|
| 공급자 속도 제한 | 전달된 429 | 동일 모델이 더 낮은 요청 빈도로 작동하는지 확인 |
| 공급자 장애 | 전달된 502/503 | 공급자 상태 페이지 확인 (예: status.openai.com) |
| 모델 폐기 또는 사용 불가 | 404 또는 모델을 찾을 수 없음 | OpenRouter 모델 목록에서 모델 ID가 여전히 유효한지 확인 |
| 지역 제한 | 403 또는 접근 거부 | 일부 공급자는 지역별로 접근을 제한함 |
| 입력이 너무 큼 | 400 (컨텍스트/토큰 관련 메시지) | 입력이 모델의 컨텍스트 윈도우를 초과하는지 확인 |
4.2 다른 공급자 라우트로 전환
OpenRouter는 요청을 업스트림 공급자로 라우팅합니다. 한 공급자가 속도 제한을 적용하고 있다면, 동일한 모델이 다른 공급자 경로를 통해 사용 가능할 수 있습니다.
다음을 확인하세요:
- 해당 모델이 OpenRouter에서 여러 공급자 옵션을 가지고 있는지
- 요청에서 공급자 선호도를 구성할 수 있는지
- 유사한 성능을 가진 폴백 모델이 사용 가능한지
4.3 오류 유형을 구분하는 재시도 로직 추가
모든 오류를 같은 방식으로 재시도하지 마세요:
async def smart_retry(make_request, max_retries=3):
for attempt in range(max_retries):
try:
return await make_request()
except Exception as e:
error_msg = str(e)
# Do NOT retry: bad request, auth error, model not found
if any(code in error_msg for code in ["400", "401", "404"]):
raise
# Retry with backoff: rate limit or provider error
if any(code in error_msg for code in ["429", "502", "503"]):
delay = min(30, (2 ** attempt) + random.uniform(0, 1))
await asyncio.sleep(delay)
else:
raise5단계: 사전에 폴백 설계하기
프로덕션 환경에서는 업스트림 오류가 발생할지가 아니라, 발생했을 때 시스템이 우아하게 성능을 낮출 것인지 아니면 다운될 것인지가 문제입니다.
폴백 체크리스트
| 폴백 계층 | 구현할 내용 | 이유 |
|---|---|---|
| 백오프 재시도 | retry-after를 준수하는 지터 지수 백오프 | 부하를 증가시키지 않고 일시적 장애를 처리 |
| 모델 폴백 | 기본 모델이 실패하면 대체 모델로 라우팅 | 한 모델 경로가 다운되어도 워크플로를 유지 |
| 공급자 폴백 | 한 공급자가 오류를 반환하면 다른 라우트 시도 | 단일 공급자 의존도를 줄임 |
| 큐 + 서킷 브레이커 | N회 연속 실패 후 해당 경로로의 전송 중단 | 재시도 폭주가 문제를 악화시키는 것을 방지 |
| 그레이스풀 디그레이드 | 더 작은 컨텍스트, 저렴한 모델, 또는 캐시된 응답 | 최종 사용자에게 완전한 장애보다 나은 경험 제공 |
통합 API 게이트웨이를 고려해야 할 때
업스트림 장애를 처리하기 위해 OpenRouter 위에 폴백 로직을 구축하고 있다면, 사실상 라우팅 계층 위에 또 다른 라우팅 계층을 구축하고 있는 셈입니다.
이 시점에서는 공급자 라우팅, 폴백, 모델 선택을 내장 기능으로 제공하는 게이트웨이를 사용하는 것이 애플리케이션 수준 코드보다 더 간단할 수 있습니다.
- 공급자 간 자동 라우팅
- 응답에 실제 사용된 모델을 반환
- OpenAI 호환 요청 형식 -- 코드 수정 불필요
- 별도의 라우팅 수수료 없음
curl https://api.evolink.ai/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "evolink/auto",
"messages": [
{"role": "user", "content": "Your prompt here"}
]
}'이것이 클라이언트 측 재시도 로직의 필요성을 없애는 것은 아니지만, 공급자 선택과 폴백을 애플리케이션 코드 밖으로 이동시킵니다.
오류 원인 트리 (참고)
OpenRouter 요청 실패
│
├── OpenRouter의 429
│ ├── 무료 티어 제한 → 계정 업그레이드
│ ├── 버스트 트래픽 → 동시성 제어 추가
│ └── 지속적 높은 트래픽 → 티어 제한 확인
│
├── "Provider returned error"
│ ├── Upstream 429
│ │ ├── 공급자 속도 제한 → 빈도 줄이기 또는 공급자 변경
│ │ └── 공유 할당량 소진 → 조직 수준 제한 확인
│ ├── Upstream 502/503
│ │ ├── 공급자 장애 → 상태 페이지 확인, 대기 또는 변경
│ │ └── 일시적 장애 → 백오프로 재시도
│ └── Upstream 400
│ ├── 컨텍스트가 너무 김 → 잘라내기 또는 모델 변경
│ ├── 잘못된 파라미터 → API 문서 확인
│ └── 모델 폐기 → 모델 ID 확인
│
└── 기타 오류
├── 401 → 유효하지 않은 API 키
├── 404 → 모델을 찾을 수 없음
└── 네트워크 오류 → 연결 확인다음 할 일
- 현재 오류를 확인하세요: 2단계를 사용하여 OpenRouter 429인지 공급자 오류인지 파악하세요.
- 적절한 수정 사항을 적용하세요: 속도 제한 수정을 공급자 오류에 적용하거나 그 반대를 하지 마세요.
- 구조화된 재시도 로직을 추가하세요: 코드에서 재시도 가능한 오류와 재시도 불가능한 오류를 구분하세요.
- 필요하기 전에 폴백을 설계하세요: 프로덕션 시스템은 단일 업스트림 경로에 의존해서는 안 됩니다.
관련 글
- How to Reduce 429 Errors in Agent Workloads -- 에이전트 특화 버스트 트래픽을 위한 심화 패턴
- Best OpenRouter Alternatives in 2026 -- OpenRouter 제한이 반복적인 문제일 때의 라우팅 옵션 비교
- Best AI API Platform for Production Reliability -- 신뢰할 수 있는 프로덕션 API 플랫폼 선택 프레임워크
FAQ
OpenRouter에서 "provider returned error"는 무엇을 의미하나요?
OpenRouter가 요청을 수신하여 업스트림 모델 공급자에게 전달했지만, 공급자가 오류를 반환했다는 의미입니다. 오류는 OpenRouter 자체가 아니라 OpenAI, Anthropic, Google 등 해당 모델을 제공하는 공급자에서 발생한 것입니다.
OpenRouter의 429와 업스트림 공급자의 429는 같은 건가요?
아닙니다. OpenRouter 수준의 429는 OpenRouter 자체의 속도 제한에 도달했음을 의미합니다. "provider returned error"로 전달된 공급자 수준의 429는 업스트림 공급자가 요청을 거부했음을 의미합니다. 해결 방법이 다릅니다.
"provider returned error"에 대해 재시도해야 하나요?
오류 유형에 따라 다릅니다. 업스트림이 502/503(일시적 장애)을 반환한 경우, 백오프로 재시도하는 것이 합리적입니다. 400(잘못된 요청)이나 404(모델을 찾을 수 없음)를 반환한 경우, 재시도해도 도움이 되지 않습니다. 요청 자체를 수정하세요.
문제가 API 키, 할당량, 공급자 중 어디에 있는지 어떻게 알 수 있나요?
다음 순서로 확인하세요: (1) API 키가 유효한가요? 간단한 테스트 요청을 시도해 보세요. (2) OpenRouter 대시보드에서 할당량과 속도 제한 사용량을 확인하세요. (3) 키와 할당량에 문제가 없다면, 오류는 업스트림 공급자에서 발생한 것일 가능성이 높습니다. 오류 메시지에서 자세한 내용을 확인하세요.
통합 API 게이트웨이로 공급자 오류를 완전히 없앨 수 있나요?
어떤 게이트웨이도 업스트림 공급자의 장애를 방지할 수는 없습니다. 하지만 라우팅과 폴백이 내장된 게이트웨이는 한 경로가 실패할 때 자동으로 대체 공급자나 모델로 전환하여 애플리케이션에 미치는 영향을 줄일 수 있습니다.
OpenRouter에서 다른 라우팅 솔루션으로 언제 전환해야 하나요?
다음 경우에 전환을 고려하세요: (1) 공급자 오류가 프로덕션에서 반복적으로 발생하는 문제인 경우, (2) OpenRouter가 제공하지 않는 폴백 로직이 필요한 경우, (3) 워크로드가 여러 모달리티(텍스트 + 이미지 + 동영상)에 걸쳐 있는 경우, (4) 라우팅 결정을 애플리케이션 코드가 아닌 게이트웨이 수준에서 관리하고 싶은 경우.


