■ API 오류별 대응
표시가 없는 문장은 공식 문서에서 확인한 내용이에요. 다른 표시는 읽는 법
왜 배우나 — 시험이 요구하는 것
시험 목표 7.3 디버깅과 운영 문제 해결 · D7 개발팀 7%Support debugging and operational issue resolution
이 개념으로 푸는 판단 (할 수 있어야 하는 것)
- 7.3③ API 오류가 쏟아질 때 무엇부터 보나? — 오류 종류별 대응 (재시도할 것 / 한도를 볼 것 / 오류가 아닌 것)
한눈에
API 오류는 HTTP 상태와 error.type(JSON)으로 온다. 할 일은 코드가 정한다
- 500·529 : 일시 오류다. 지수 백오프로 재시도한다
- 429 : 한도다(속도 또는 지출 상한)
- 504 : 긴 요청은 스트리밍으로 보낸다
- 400대 : 내 요청·키·권한을 고친다
모든 응답에 request-id 헤더가 붙는다(오류 본문에는 같은 값이 request_id 로 온다). 이 값이 문의·추적의 열쇠다. 거절은 오류가 아니다(HTTP 200). 자세한 것은 ■ stop_reason 으로 분기 에 있다
비유 5xx 는 백오프 재시도와 서킷 브레이커로, 429 는 스로틀·쿼터 확인으로, 4xx 는 클라이언트 버그 수정으로 다룬다. 추적은 X-Request-ID 로 게이트웨이·백엔드 로그를 잇는 것과 같다
ELI5
가게에 전화했는데 안 되는 이유가 여러 가지예요.
- "지금 손님이 너무 많아요" → 조금 있다 다시 걸면 돼요 (500·529).
- "오늘 주문 한도를 넘었어요" → 다시 걸어도 소용없을 때가 있어요 (429).
- "주문서가 잘못 적혔어요" → 주문서를 고쳐야 해요 (400대).
- 전화마다 붙는 접수 번호를 적어 두면, 나중에 가게에 물어볼 수 있어요 (request-id).
개념 설명
원리
오류는 "누구 문제인가"를 알려 준다
- 5xx(500·529·504)는 Anthropic 쪽 또는 요청 처리 쪽의 일시 문제다. 같은 요청을 잠시 뒤 다시 보내면 대개 풀린다. 그래서 지수 백오프로 재시도한다.
- 429 는 내 조직의 한도다. 아래 두 가지가 섞여 있다. 구분은 ■ rate limit 에 있다.
- 기다리면 풀리는 것 : rate limit(속도 제한)이다.
retry-after가 있다 - 기다려도 안 풀리는 것 : 티어 월 지출 상한이다.
retry-after가 없다
- 기다리면 풀리는 것 : rate limit(속도 제한)이다.
- 400대는 내 요청 자체가 틀린 것이다. 몇 번을 다시 보내도 결과가 같다. 요청·키·권한을 고친다.
- 504 는 요청이 너무 오래 걸린 것이다. 재시도보다 요청 방식을 바꾼다(스트리밍·배치).
오류가 아닌 실패가 있다
- 거절은 HTTP 200 과
stop_reason: "refusal"로 온다. 오류율 감시에 보이지 않는다. - 스트리밍은 200 을 먼저 보낸 뒤 중간에
error이벤트가 올 수 있다. HTTP 상태만 보면 놓친다.
재시도는 이미 누가 하고 있다
- 공식 SDK 는 일시 오류를 기본 2번 재시도한다. Claude Code 는 기본 10번 재시도하고, 포기한 뒤에야
api_error를 1번 남긴다. - 그 위에 또 재시도를 감싸면 시도 수가 곱해진다. 그래서 한도와 비용을 더 먹는다(업계 일반).
추적은 request-id 로 한다
- 모든 응답에 붙는다. 오류 본문에도 같은 값이 있다. 지원 문의와 로그 대조의 열쇠다.
핵심 질문은 두 개다
- 이 실패는 기다리면 풀리나, 고쳐야 풀리나?
- 내 감시가 이 실패를 볼 수 있나(200 인 실패 포함)?
규칙과 판단
갈림길
①② 상태 코드로 가르기 [7.3③]
error.type 도 함께 본다api_error
백오프 재시도
계속되면 request ID 와 함께 지원팀에 문의한다
overloaded_error
일시 과부하
내 한도 문제가 아니다. 백오프로 재시도한다
timeout_error
긴 요청
스트리밍 Messages API 나 Message Batches 를 쓴다
rate_limit_error
한도
rate limit 또는 지출 상한이다. 자세한 것은 ■ rate limit 에 있다
요청을 고친다
형식·키·권한·경로·크기를 고친다. SDK 가 자동 재시도하는 일시 오류(연결·429·5xx)가 아니다. 400 은 재시도해도 안 되는 오류다. 내가 건 지출 한도에 도달해도 400 이 온다. 그때는 한도를 올린다
다음 물음 — 200 인데 무엇이 왔나?
④ 오류가 아닐 때 [7.3③] [4.6③]
refusal
거절
HTTP 200 과 stop_reason: "refusal" 이 온다. 자세한 것은 ■ stop_reason 으로 분기 에 있다
error 이벤트
스트림 오류 처리
200 뒤 오류는 표준 오류 처리를 따르지 않는다. 오류 이벤트를 따로 처리한다
③⑤ 재시도는 누가 [7.3③]
이미 재시도한다
연결 오류·429·5xx 를 지수 백오프로 기본 2번 재시도한다. retry-after 를 따른다. max_retries 로 조정한다
포기한 뒤 1번 기록
api_error 는 재시도를 다 한 뒤 1번 남는다. attempt 11 은 일시 오류로 재시도를 소진했다는 뜻이다(기본 10번)
request-id
모든 응답 헤더에 있다. 오류 본문에는 request_id 로 있다
흐름
그림 속 이름·금액·시간·토큰 수는 예시예요. 공식 한도·동작은 카드 본문 값이 기준.
장면 글로 보기
칸 : 앱 → SDK → API
규칙 (SDK) : 연결 오류·429·5xx 를 지수 백오프로 기본 2번 재시도한다
질문 : 이 오류, 다시 보내면 될까?
① 500 은 백오프 후 요청 ID 로 문의 ✓
- 시작 : 앱 — 쪽지 : POST /v1/messages
- 실패 : API → SDK : 500
api_error가 온다 — 쪽지 : HTTP 500 / type:api_error/ request_id: req_018… - 재시도 : SDK → API : 지수 백오프로 기본 2번 재시도한다 — 쪽지 : 재시도 1/2 · 백오프 / 재시도 2/2 · 더 길게
- 문의 : SDK → 앱 : 계속되면 요청 ID 로 문의한다 — 쪽지 : 500 예외 · 재시도 소진 / request-id: req_018…
- 끝 : Anthropic 내부 오류다. 백오프로 재시도하고, 계속되면 요청 ID 로 문의한다
② 스트림 중간 오류 ≠
- 시작 : 앱 — 쪽지 : POST /v1/messages /
stream: true - 응답 : API → 앱 : HTTP 200 으로 스트림이 시작된다 — 쪽지 : HTTP 200 / 글자가 흘러옴…
- 오류 : API → 앱 : 스트림 중간에 오류 이벤트가 온다 — 쪽지 : event: error / type:
overloaded_error - 표시 : 앱 : 200 만 보고 성공으로 처리한다 — 쪽지 : 로그: 200 · 성공 / (답은 중간에 끊김)
- 끝 : 200 뒤 오류는 표준 오류 처리를 따르지 않는다. 오류 이벤트를 따로 처리해야 한다
③ 긴 요청 504 는 스트리밍으로 ✓
- 시작 : 앱 — 쪽지 : POST /v1/messages /
max_tokens: 큰 값 /stream없음 - 요청 : 앱 → API : 큰
max_tokens를 비스트리밍으로 보낸다 — 쪽지 : 응답 기다리는 중… / (연결은 유휴) - 끊김 : API : 유휴 연결이 끊긴다 — 쪽지 : HTTP 504 / type:
timeout_error - 바꿈 : 앱 → API : 스트리밍이나 Message Batches 로 바꾼다 — 쪽지 :
stream: true / → 청크가 계속 옴 - 끝 : 긴 요청은 스트리밍으로 보낸다. 타임아웃 값만 늘리지 않는다
나머지 규칙
-
긴 요청 : 스트리밍·배치 없이 큰
max_tokens를 쓰는 것은 피한다. 일부 네트워크가 유휴 연결을 끊어 응답 없이 실패하거나 시간이 초과된다. 배치는 결과를 폴링해 네트워크 위험을 덜어 준다. SDK 는 비스트리밍 요청이 10분 시간 초과를 넘을지 검증하고 TCP keep-alive 를 켠다 [7.3③]
규칙 원문 ①②③④⑤ (갈림길로 그린 규칙)
-
코드별 뜻과 할 일 (2026-09-28 조회) [7.3③]
코드 type뜻 할 일 500 api_error Anthropic 내부의 예기치 않은 오류 지수 백오프로 재시도한다. 계속되면 request ID 와 함께 지원팀에 문의한다 529 overloaded_error API 일시 과부하 백오프로 재시도한다 (내 한도 문제가 아니다. ■ rate limit) 504 timeout_error 처리 중 시간 초과 긴 요청은 스트리밍 Messages API 로 보낸다 429 rate_limit_ error rate limit · 티어 월 지출 상한 · Claude Code 워크스페이스 지출 한도 지출 상한 429 는 retry-가 없고, 풀릴 때까지 계속 실패한다. 가르는 법은 ■ rate limit · 규칙 ⑤ 에 있다after 400 invalid_request_ error 요청 형식·내용 문제 · 내가 건 지출 한도 도달도 400 요청을 고친다. 한도를 올린다 401 · 403 키 문제(형식·취소·만료) · 키에 그 리소스 권한이 없다 키·워크스페이스 설정을 확인한다 413 request_too_ large 크기 초과 (Messages 32 MB · Batch 256 MB) 요청을 줄인다 409 conflict_error 리소스 현재 상태와 충돌 충돌을 풀고 재시도한다 -
사용량이 갑자기 치솟으면 529 대신 429 가 날 수 있다. 이것이 가속 한도(acceleration limits)다 (2025-08-11 릴리스 노트) [7.3③]
짧은 폭주는 ■ rate limit · 규칙 ① 에서 다룬다
-
재시도는 SDK 가 이미 한다 : 공식 SDK 는 연결 오류·rate limit(속도 제한)·5xx 를 지수 백오프로 기본 2번 재시도한다.
retry-after가 있으면 따른다.max_retries로 조정하거나 끈다 [7.3③]오류는 SDK 의 타입 예외로 잡는다. 메시지 문자열로 매칭하지 않는다. 가장 구체적인 클래스부터 잡는다
Claude Code 는 내부에서 재시도한다(
CLAUDE_CODE_MAX_RETRIES기본 10 · 상한 15). 포기한 뒤에만claude_code.api_error를 1번 남긴다attempt11 은 일시 오류로 재시도를 소진했다는 뜻이다. 더 작으면 400 같은 재시도 안 되는 오류다. 회복 여부는 같은session.id에 뒤이은api_request가 있나로 본다 (2026-09-28 조회) -
오류가 아닌 것 : 거절은 HTTP 200 과
stop_reason: "refusal"로 온다. 그래서 오류 집계나api_error에 잡히지 않는다. Claude Code 는claude_code.api_refusal이벤트를 남긴다. 자세한 것은 ■ stop_reason 으로 분기 에 있다 [7.3③] [4.6③]스트리밍은 200 뒤에도 오류가 온다.
event: error안의overloaded_error는 비스트리밍의 529 에 해당한다. 표준 오류 처리를 따르지 않는다 -
추적 : 모든 응답에
request-id헤더가 붙는다(예req_018…). 오류 본문에는 같은 값이request_id로 온다 (2025-08-19~) [7.3③]Python·TypeScript SDK 는
_request_id속성으로 읽는다. 다른 헤더는with_raw_response로 읽는다Claude Platform on AWS 는 ID 가 두 개다.
x-amzn-requestid는 CloudTrail 조회용이다.request-id는 Anthropic 지원 티켓용이다Claude Code 텔레메트리의
request_id도 같은 값이다. 타임아웃처럼 서버 ID 가 생기지 않은 실패는client_request_id를 쓴다
더 깊이 : 판단 규칙 · 상황 변수 (설명)
판단 규칙
| 조건 | 답 | 근거 |
|---|---|---|
500 api_ | 지수 백오프로 재시도한다. 계속되면 request ID 로 지원팀에 문의한다 | errors "Retry the request with exponential backoff; if the error persists, contact support with the request ID." |
529 overloaded_ | 일시 과부하다. 백오프로 재시도한다 | errors (SDK 가 5xx 를 재시도) |
504 timeout_ | 긴 요청은 스트리밍 Messages API 로 보낸다 | errors |
429 · retry- 가 없다 · enforced_ | 티어 지출 상한이다. 재시도는 무의미하다. 상향을 요청한다 | errors · rate-limits |
429 · retry- 가 있다 | 그 시간 뒤에 재시도한다(이르면 또 실패한다) | rate-limits |
| 400 · 내 지출 한도 도달 | 400 으로 온다. 한도를 올린다 | errors |
| 오류 처리 코드 | SDK 타입 예외를 구체적인 것부터 잡는다(문자열 매칭 X) | errors |
| 200 인데 빈 답이다 | 거절이다. 오류가 아니다. 자세한 것은 ■ stop_reason 으로 분기 에 있다 | monitoring-usage |
| 스트리밍 200 뒤 오류 | 오류 이벤트를 따로 처리한다 | errors · streaming |
| 문의·추적 | request- 헤더와 본문 request_ 를 쓴다 | errors |
상황 변수
| 변수 | 값 | 답 쪽 | 등급 | 근거 |
|---|---|---|---|---|
| 호출 경로 | 공식 SDK | 일시 오류는 이미 2번 재시도한다. max_ 로 조정한다 | errors | |
| 호출 경로 | Claude Code | 기본 10번 재시도 후 api_ 1건을 남긴다. 횟수는 attempt 로 본다 | monitoring-usage | |
| 호출 경로 | 직접 HTTP | 백오프를 직접 짠다 | 업계 일반 | — |
| 사용량 모양 | 갑자기 치솟는다 | 529 대신 429(가속 한도)일 수 있다 | 릴리스 노트 (2025-08-11) | |
| 사용량 모양 | 월말에 누적된다 | 지출 상한 429 가 나면 다음 달 1일 00:00 UTC 까지 멈춘다 | rate-limits | |
| 요청 길이 | 큰 max_ · 비스트리밍 | 스트리밍이나 배치를 쓴다 | errors | |
| 플랫폼 | Claude Platform on AWS | ID 가 두 개다. CloudTrail 은 x-, 지원 티켓은 request- 를 쓴다 | errors | |
| 응답 모양 | 스트리밍 | HTTP 상태만으로는 부족하다 | errors |
연습 문제
매일 밤 긴 월간 보고서를 만드는 앱이 큰 max_tokens 로 스트리밍 없이비스트리밍 요청을 보낸다. 요즘 HTTP 504 timeout_error504 로 자주 실패하자 개발자는 클라이언트 타임아웃 값을 더 늘리려 한다. 어떻게 고쳐야 하나?
시험 대비
함정
- "피크에 실패가 급증하니 모델이 불안정하다. 모델을 바꾼다" 는 함정이다. 상태 코드부터 본다. 5xx·529 는 일시 오류(백오프)이고, 429 는 한도다. 모델 품질 문제가 아니다 업계 일반 단 한도는 모델마다 따로라 다른 모델을 섞으면 429 는 덜 수 있음 ■ rate limit · 규칙 ④
- "429 면 즉시 무한 재시도한다" 는 함정이다.
retry-after보다 이르면 또 실패한다. 지출 상한 429 는 계속 실패한다 - "500 이 계속돼도 재시도만 한다" 는 함정이다. 계속되면 request ID 로 문의한다
- "504 면 타임아웃 값만 늘린다" 는 함정이다. 긴 요청은 스트리밍으로 보낸다
- "오류율 대시보드가 조용하니 정상이다" 는 함정이다. 거절은 200 으로 온다. 스트림 중간 오류는 200 뒤에 온다
- "오류 메시지 문자열로 분기한다" 는 함정이다. SDK 타입 예외를 구체적인 것부터 잡는다
- "Claude Code
api_error1건은 한 번 실패다" 는 함정이다. 재시도를 다 한 뒤 1번 남는다. 횟수는attempt로 본다 - "SDK 위에 재시도 루프를 또 감싼다" 는 함정이다. SDK 가 이미 2번 재시도한다. 겹치면 시도 수가 곱해진다 업계 일반
- "400 이니 한도는 아니다" 는 함정이다. 내가 건 지출 한도에 도달해도 400 이 온다
신호
"Retry the request with exponential backoff; if the error persists, contact support with the request ID."
"A tier spend-cap 429 has no retry-after header and keeps failing until access resumes"
"The official SDKs automatically retry transient failures (such as connection errors, rate limits, and 5xx server errors) with exponential backoff, twice by default, honoring the retry-after header when present."
"Consider using the streaming Messages API for long-running requests."
"an error can occur after the API returns a 200 response."
"Every API response includes a unique request-id header."
"Catch the SDK's typed classes rather than string-matching error messages, handling the most specific classes first."
"Refusals arrive on a successful response stream rather than as an HTTP error, so the api_error event doesn’t fire for them."
"Previously, 529 (overloaded_error) errors would occur in similar scenarios." (릴리스 노트 2025-08-11)
더 깊이 : 뒤집히는 때 · 오답 재료 (설명)
뒤집히는 때
1. 모델을 바꾸는 게 맞는 때
- 조건 : 오류가 한 모델의 429 에 몰려 있다. 또는 200 인데
refusal로 빈 답이 온다. - 판단 : "모델 교체 = 엉뚱한 계층" 은 5xx·529 일 때 이야기다. rate limit 은 모델마다 따로다. 그래서 다른 모델을 섞으면 그 모델의 한도까지 더 쓴다(■ rate limit · 규칙 ④). 거절은 같은 모델에 다시 보내면 대개 또 거절된다. 그래서 다른 모델로 보낸다(■ stop_reason 으로 분기 · 규칙 ③).
- 근거 : rate-limits 카드 ④ · stop-reason 카드 ③
- 그래도 첫 수는 상태 코드와
stop_reason확인이다. 그것을 안 보고 "불안정하니 교체" 하는 보기는 오답 쪽이다.
2. 재시도를 겹쳐 감쌌을 때
- 조건 : 앱이 SDK 호출을 자체 재시도 4번으로 감쌌다. SDK 는 기본 2번 재시도한다.
- 계산 : 앱 1회 호출에 SDK 가 최대 3번 시도한다(1 + 2). 앱은 최대 5번 호출한다(1 + 4). 그래서 요청 하나가 최대 15번 API 를 두드린다.
- 판단 : 과부하·rate limit 상황에서 시도가 곱해지면 회복이 늦어진다. SDK 의
max_retries를 조정하거나 겹친 재시도를 걷어 낸다. - 등급 : 계산 (SDK 기본 2번은 확인이다. "회복이 늦어진다" 는 업계 일반이다)
- 근거 : errors
3. Claude Code 의 api_error 1건
- 조건 : 텔레메트리에
claude_code.api_error가 1건 있다.attempt는 11 이다. - 판단 : 1번 실패가 아니다. 일시 오류로 11번(첫 시도 + 기본 10번 재시도) 다 해 보고 포기한 것이다.
attempt가 1~2 처럼 작으면 원인은 둘 중 하나다. 400 같은 재시도 안 되는 오류이거나, 자체 재시도 예산이 작은 원인이다(예 AWS·Google Cloud 자격증명 로드 실패는 최대 2번). - 회복 여부 : 같은
session.id에서 그 오류 뒤에api_request가 이어지나로 본다. - 근거 : monitoring-usage
4. 429 인데 기다려도 안 풀리는 때
- 조건 : 월 중순부터 모든 요청이 429 다. 헤더에
retry-after가 없다. - 판단 : rate limit 이 아니라 티어 월 지출 상한이다.
error.details.error_code는enforced_spend_limit_reached다. SDK 재시도도 계속 실패한다. 그래서 상향을 요청한다. - 근거 : errors · rate-limits
오답 재료
| 오답 | 왜 끌리나 | 왜 틀리나 | 등급 | 근거 |
|---|---|---|---|---|
| "피크에 실패가 급증하니 모델이 불안정, 모델 교체" | 실패가 모델 호출에서 나니 모델 탓 같다 | 상태 코드부터 본다. 5xx·529 는 일시 오류, 429 는 한도다. 엉뚱한 계층을 고치는 것이다 (단 뒤집히는 때 1) | 업계 일반 + 확인 | errors |
| "429 에 즉시·무한 재시도" | 재시도가 기본 대응 같다 | retry- 보다 이르면 또 실패한다. 지출 상한 429 는 계속 실패한다 | rate-limits · errors | |
| "500 이 계속돼도 재시도 횟수만 늘린다" | 언젠간 될 것 같다 | 계속되면 request ID 로 문의한다 | errors | |
| "504 면 타임아웃 값만 늘린다" | 설정 한 줄로 끝난다 | 긴 요청은 스트리밍·배치로 보낸다. 네트워크가 유휴 연결을 끊는다 | errors | |
| "오류율(5xx) 대시보드가 조용하니 정상" | 오류가 없어 보인다 | 거절은 200 이다. 스트림 중간 오류는 200 뒤에 온다 | monitoring-usage · errors | |
| "오류 메시지 문자열로 분기" | 메시지에 이유가 적혀 있다 | SDK 타입 예외를 구체적인 것부터 잡는다. type 값은 늘어날 수 있다 | errors | |
| "400 이니 한도 문제는 아니다" | 한도 = 429 로 외웠다 | 내가 건 지출 한도 도달은 400 이다 | errors | |
| "SDK 위에 재시도 루프를 또 감싸 안정성 확보" | 겹겹이 방어 같다 | SDK 가 이미 2번 재시도한다. 겹치면 시도 수가 곱해진다 | 계산 | 뒤집히는 때 2 |
참고
더 깊이 : 출처 · 상태 · 미해결 (참고)
미해결
- 목록 7.3③ 의 "529 overloaded = 일시 과부하" 뒤 처방 : errors 문서의 529 줄에는 처방 문장이 없다. "백오프 재시도" 는 SDK 가 5xx 를 재시도한다는 17줄과 ■ rate limit 카드에서 가져왔다.
- 가속 한도(acceleration limits)는 2025-08-11 릴리스 노트에만 있다. 지금 rate-limits 문서에는 이 단어가 없다(검색어
acceleration). 지금 문서의 가까운 문장은 "Short bursts of requests can exceed the limit" 다(■ rate limit). - 408·409 를 SDK 가 자동 재시도하는지는 확인하지 못했다. errors 문서는 "such as connection errors, rate limits, and 5xx" 예시만 든다. 409 는 "충돌을 풀고 재시도" 만 확인했다.
- 목록의 영어 신호 두 개(500 줄 · 지출 상한 429 줄)는 원문에서 찾았다. 목록 그대로다 ✓. 목록의 "Claude Code 감시도 api_error 가 아니라 api_refusal" 도 monitoring-usage에서 확인했다 ✓.