GLM API의 오류에는 두 층이 있습니다. 바깥층은 HTTP 상태 코드이고 안쪽층은 응답 본문의 비즈니스 코드입니다. 바깥층만 보면 오판하기 쉽습니다. 예를 들어 계정 미납도 429로 반환됩니다. 진단 순서는 비즈니스 코드와 오류 메시지를 먼저 읽고, 요청 ID나 오류 ID를 찾고, 최소 요청으로 재현한 다음, 마지막에야 파라미터를 바꾸거나 모델을 교체하는 것입니다.
이 글은 401, 403, 404, 429, 5xx, 타임아웃으로 나누어 비즈니스 코드 대조표, 오류 처리 코드, 지원팀에 연락하기 전 체크리스트를 제시합니다. 모델과 가격은 사이트 내 모델 가격을 기준으로 합니다.
안내: Zhipu, GLM, BigModel은 관련 권리자의 상표이며 이 글은 기술 설명 목적일 뿐 Zhipu와 소속 또는 대리 관계가 없습니다. 오류 코드, 속도 제한 기준, 인터페이스 동작은 버전에 따라 조정될 수 있으며 최종적으로는 공식 문서와 실제 응답을 기준으로 합니다.
1. 먼저 두 층의 오류를 구분하기
HTTP 상태 코드는 프로토콜 계층의 결과를, 비즈니스 코드는 구체적인 원인을 설명합니다. 같은 401이라도 인증 헤더 누락, Token 만료, 2차 인증일 수 있습니다. 같은 429라도 속도 제한, 모델 혼잡, 미납, 요금제 상한일 수 있습니다. 비즈니스 코드를 로그에 남기는 것이 장애 대응 효율을 가장 높이는 첫 단계입니다.
| HTTP | 흔한 비즈니스 코드 | 의미 | 재시도 적합 여부 |
|---|---|---|---|
| 401 | 1000 / 1001 / 1003 / 1005 | 인증 실패, 인증 헤더 누락, Token 만료, 2차 인증 | 아니요, 자격 증명 먼저 수정 |
| 403 | 1220 | 해당 API 또는 모델 접근 권한 없음 | 아니요, 요금제와 권한 확인 |
| 400 | 1210 / 1211 / 1221 / 1222 / 1261 | 파라미터 오류, 모델 없음, API 종료 또는 없음, Prompt 초과 | 아니요, 요청 수정 |
| 429 | 1113 | 계정 미납 | 아니요, 먼저 충전 |
| 429 | 1302 / 1305 | 속도 제한, 모델 접근량 과다 | 예, 백오프 후 재시도 |
| 429 | 1308 / 1310 | 주기 상한, next_flush_time 기준 재설정 | 재설정 대기, 강행 재시도 금지 |
| 429 | 1311 / 1313 / 1315 | 요금제 모델 권한 없음, 공정 사용 제한, Key 유형 불일치 | 아니요, 요금제와 Key 확인 |
| 500 | 1200 / 1230 / 1234 | 내부 오류, 프로세스 오류, 네트워크 오류(오류 ID 포함) | 예, 백오프 후 오류 ID 보존 |
표는 가장 흔한 대응이며 전체 목록은 공식 문서를 기준으로 합니다. 스트리밍 중단은 비즈니스 코드가 없을 수 있고 원인은 finish_reason이나 마지막 데이터 조각에 나타납니다.
2. 401: 네 가지 인증 실패
401은 신원이 검증되지 않았다는 뜻이며 모델 능력이나 잔액과는 대개 무관합니다. 공식 오류 코드는 흔한 원인을 비교적 세분화해 설명합니다.
- 1000 신원 검증 실패: Key 오류, 복사 불완전, 또는 삭제됨.
- 1001 요청 헤더 인증 파라미터 누락:
Authorization: Bearer <key>가 없거나 프록시가 버림. - 1003 Token 만료: Key에 유효기간이 있거나 콘솔에서 교체됨.
- 1005 2차 인증 활성화: 플랫폼 요구에 따라 검증 완료.
진단은 다음 순서로 하십시오.
- 요청 헤더 형식을 확인합니다. 콜론 뒤 공백 하나, Key 앞뒤에 따옴표나 줄바꿈이 없어야 합니다.
- 환경 변수 접두사를 출력해 빈 값이나 이전 값이 아닌지 확인합니다.
- Key 유형을 확인합니다. 표준 모델 API, Coding Plan, 팀 또는 기업 Key는 따로 관리하며 혼용할 수 없습니다.
- Base URL과 Key 소속이 일치하는지 확인합니다. 공식 Key에는 공식 주소, 게이트웨이 Key에는 게이트웨이 주소를 씁니다.
- 새 Key로 최소 요청을 실행해 Key 문제인지 프록시나 게이트웨이 설정 문제인지 구분합니다.
채팅 창에서 Key를 복사하면 공백이나 줄바꿈이 가장 쉽게 섞여 들어갑니다. 한 단어만 출력하는 요청을 먼저 실행하면 대부분의 저급 오류를 배제할 수 있습니다.
3. 403과 404: 권한, 경로와 모델명
403의 흔한 비즈니스 코드는 1220이며 현재 계정이 해당 API나 모델에 접근할 권한이 없음을 뜻합니다. 요금제에 해당 모델이 포함되는지, Key가 해당 제품 유형에 속하는지, 개통되지 않은 인터페이스를 호출하지 않았는지 확인하십시오. 이런 오류는 재시도가 무의미하며 권한을 바꾸거나 Key를 교체해야 합니다.
404는 대개 "서비스가 죽었다"가 아니라 주소가 틀린 것입니다. Base URL에 /v1이 더 있거나 빠졌고, SDK가 자동으로 붙인 뒤 전체 경로를 또 수동으로 썼고, 리버스 프록시 재작성 규칙이 경로를 망가뜨렸을 수 있습니다. GLM의 모델명 오류는 보통 400의 1211로 반환되고 API 종료 또는 없음은 1221과 1222에 해당합니다. 따라서 404를 보면 주소를 먼저 확인하고 1211을 보면 모델명을 확인하십시오.
모델명은 공식 문서와 사이트 가격 페이지를 기준으로 하며 기억에 의존해 버전 번호를 쓰지 마십시오. 모델을 업그레이드할 때는 테스트 환경에서 파라미터 호환성을 먼저 확인하십시오.
4. 429: 비즈니스 코드를 먼저 읽고 재시도 여부 결정
429는 가장 잘못 처리되기 쉬운 오류입니다. 최소한 다섯 가지 상황을 포함합니다.
- 1113 계정 미납: 충전 전 재시도는 의미가 없습니다.
- 1302 속도 제한 도달: 동시성을 낮추거나 백오프합니다.
- 1305 모델 현재 접근량 과다: 보통 피크와 관련되며 백오프 후 재시도하고 필요하면 대체 모델로 전환합니다.
- 1308, 1310 주기 사용 상한 도달: 오류 메시지에 재설정 시간이 있으므로 할당량 회복을 기다립니다.
- 1309, 1311, 1313, 1315: 요금제 만료, 모델 미개방, 공정 사용 제한, Key 유형 불일치이므로 설정을 바꿔야 효과가 있습니다.
1302, 1305 같은 순간적 속도 제한만 자동 재시도에 적합하고 나머지는 재시도가 장애 시간을 늘릴 뿐입니다. 속도 제한 기준(동시성, 분당 요청 수, Token 속도)은 요금제와 모델에 따라 달라지므로 콘솔과 공식 문서를 기준으로 합니다.
5. 5xx와 타임아웃: 따로 진단하기
500 계열에는 1200 내부 오류, 1230 프로세스 오류, 1234 네트워크 오류가 있습니다. 1234는 보통 오류 ID를 포함하므로 지원팀에 연락할 때 반드시 보존하십시오. 5xx가 지속되면 먼저 백오프하고 서비스 상태나 제공자 공지를 확인하며 고빈도 재시도는 하지 마십시오.
타임아웃은 세 구간으로 나눠 봐야 합니다. 연결 타임아웃은 DNS, 출구, 프록시 도달 불가이고, 첫 Token 지연은 대개 업스트림 대기나 입력 과다이며, 읽기 타임아웃은 출력이 너무 길거나 추론 시간이 길 때 많습니다. 세 가지 처리 방식이 다르므로 타임아웃 값만 키우면 안 됩니다.
스트리밍 요청이 중단되면 HTTP 오류 코드도 비즈니스 코드도 없을 수 있습니다. 수신한 내용과 마지막 데이터 조각을 먼저 기록하고 finish_reason을 확인한 뒤 네트워크 흔들림, 프록시 단절, 업스트림 타임아웃 중 무엇인지 판단하십시오. 잘린 내용을 완전한 결과로 바로 저장하지 마십시오.
6. 요청 ID와 로그: 장애 대응의 증거
공식 응답이 모든 인터페이스에서 같은 이름의 요청 ID를 제공한다고 가정할 수 없으며 필드명은 실제 응답과 문서를 기준으로 합니다. 엔지니어링에서 더 안전한 방법은 이중 기록입니다. 클라이언트가 trace_id를 생성해 모든 재시도에 붙이고, 업스트림이 반환한 오류 본문과 그 안의 request id, error id 필드를 원형 그대로 보존합니다.
로그에는 최소한 시간, trace_id, Base URL, 모델명, HTTP 상태 코드, 비즈니스 코드, 오류 메시지, 소요 시간, 재시도 횟수, 스트리밍 여부를 포함합니다. Key는 앞 몇 자리나 해시만 기록하고 사용자 원문과 전체 응답을 통째로 저장하지 마십시오.
이 필드는 자신이 보기 위한 것만이 아닙니다. 지원팀에 연락할 때 trace_id, 비즈니스 코드, 최소 재현 요청이 포함된 기록은 "가끔 오류가 납니다"라는 한마디보다 훨씬 유용합니다.
7. 재시도와 백오프: 코드 예시
다음 코드는 SDK 자동 재시도를 끄고 비즈니스 코드에 따라 재시도 여부를 결정하며 trace_id, 상태 코드, 비즈니스 코드를 함께 출력합니다. 네트워크 타임아웃은 따로 처리하고 재시도에는 상한이 있습니다.
import os
import random
import time
import uuid
import httpx
from openai import OpenAI, APIConnectionError, APIStatusError, APITimeoutError
client = OpenAI(
api_key=os.environ["GLM_API_KEY"],
base_url=os.environ.get(
"GLM_BASE_URL", "https://open.bigmodel.cn/api/paas/v4"
),
timeout=httpx.Timeout(connect=5.0, read=120.0, write=30.0, pool=10.0),
max_retries=0, # SDK 자동 재시도를 끄고 아래 로직으로 일원화
)
RETRYABLE_CODES = {1302, 1305} # 속도 제한, 모델 혼잡. 미납과 요금제 상한은 제외
def ask(prompt: str, max_attempts: int = 4) -> str:
trace_id = uuid.uuid4().hex[:12]
for attempt in range(1, max_attempts + 1):
try:
resp = client.chat.completions.create(
model=os.environ["GLM_MODEL"],
messages=[{"role": "user", "content": prompt}],
max_tokens=1024,
)
return resp.choices[0].message.content
except APIStatusError as exc:
code = None
try:
code = int(exc.response.json().get("code"))
except Exception:
pass
print(
f"trace={trace_id} attempt={attempt} "
f"http={exc.status_code} code={code} "
f"body={exc.response.text[:500]}"
)
retryable = exc.status_code >= 500 or (
exc.status_code == 429 and code in RETRYABLE_CODES
)
if not retryable or attempt == max_attempts:
raise
except (APITimeoutError, APIConnectionError) as exc:
print(f"trace={trace_id} attempt={attempt} err={type(exc).__name__}")
if attempt == max_attempts:
raise
wait = min(2 ** (attempt - 1), 20) + random.uniform(0, 1)
time.sleep(wait)
raise RuntimeError("재시도 횟수를 모두 사용했습니다")
세 가지 규칙을 보태십시오. 서버가 Retry-After를 반환하면 우선 존중하고, 재시도 예산은 여러 서비스가 겹치지 않도록 전역으로 통제하며, 부작용이 있는 요청은 멱등 키로 상태를 먼저 확인한 뒤 재전송 여부를 결정합니다.
8. 동시성 관리: 재시도 횟수를 늘리는 것보다 효과적
속도 제한 문제는 보통 재시도가 아니라 진입점 관리로 해결합니다.
- 서비스마다 독립 Key와 동시성 상한을 설정합니다.
- 배치 작업을 분할하고 시간을 분산해 정시 트래픽 급증을 피합니다.
- 큐로 피크를 깎고 실패 작업은 지연 큐로 보내 제자리에서 맴돌지 않게 합니다.
- 429 비율과 P95 지연을 모니터링하고 급증하면 동시성을 먼저 낮춥니다.
- 대체 모델이나 대체 진입점을 준비하되 전환 전에 파라미터 호환성을 확인합니다.
동시성 상한, 분당 요청 수, Token 속도의 구체적인 기준은 요금제와 모델에 따라 달라지므로 콘솔과 공식 문서를 기준으로 합니다. 다른 사람의 숫자를 그대로 복사하지 말고 자체 실측 결과로 설정하십시오.
9. 지원팀에 연락하기 전 체크리스트
- 발생 시간과 시간대, 장애가 집중적으로 폭발했는지.
- Base URL, 인터페이스 경로, 모델명, 요청 방식.
- HTTP 상태 코드, 비즈니스 코드, 전체 오류 메시지.
- 오류 ID 또는 요청 ID. 없으면 자체 생성한
trace_id를 제공. - 재현 가능한 최소 curl 요청. Key는 마스킹.
- 스트리밍 여부, 긴 컨텍스트 여부, 최근 설정 변경 여부.
- 영향 범위: 단일 Key, 단일 프로젝트, 전체 서비스 중 어디까지인지.
이 항목을 준비해야 지원팀이 바로 원인을 찾을 수 있고 정보를 주고받느라 시간을 낭비하지 않습니다. 장애가 끝날 때마다 모니터링과 경고를 보강하고 사용자 피드백을 기다리지 마십시오.
10. 자주 묻는 질문
1. 429는 항상 속도 제한인가요?
아닙니다. 429는 미납(1113), 주기 상한(1308, 1310), 요금제 모델 권한 없음(1311), 공정 사용 제한(1313)일 수도 있습니다. 비즈니스 코드를 먼저 읽고 백오프, 충전, 설정 변경 중 무엇을 할지 결정하십시오.
2. 401에서 새 Key로 바꿔도 실패하면 어떻게 하나요?
요청 헤더가 Authorization: Bearer <key>인지, 환경 변수가 로드되었는지, Key 유형과 인터페이스가 맞는지, Base URL과 Key 소속이 일치하는지, 리버스 프록시가 인증 헤더를 버리지 않았는지 확인하십시오.
3. 타임아웃은 재시도해야 하나요?
연결 실패와 읽기 타임아웃에만 제한된 횟수로 재시도하고 지수 백오프를 설정하십시오. 부작용이 있는 업무는 실행 여부를 먼저 확인해 중복 주문이나 중복 쓰기를 피하십시오.
4. 스트리밍 출력이 중간에 끊기면 어떻게 진단하나요?
수신한 내용, 마지막 데이터 조각, finish_reason을 기록해 네트워크 흔들림, 프록시 단절, 업스트림 타임아웃을 구분하십시오. 클라이언트는 재연결과 중복 제거를 지원해야 하며 잘린 내용을 저장하지 마십시오.
5. 오류 메시지에 상태 코드만 있고 비즈니스 코드가 없으면 어떻게 하나요?
전체 응답 본문과 응답 헤더를 보존하고 trace_id, Base URL, 모델명, 최소 재현 요청을 기록한 뒤 서비스 제공자에게 연락하십시오. 게이트웨이를 경유한다면 게이트웨이 측에도 같은 정보를 제공해 업스트림 로그와 대조할 수 있게 하십시오.
다음 단계
먼저 ZSQH AI Gateway에서 테스트 Key를 만들고 401, 403, 429, 5xx, 타임아웃을 각각 한 번씩 연습한 뒤 운영 모니터링에 연결하십시오. 사용 가능 모델과 과금 방식은 모델 가격에서 확인할 수 있습니다.
