콘텐츠로 이동

오류 처리

Continuum Router는 HTTP 경계에서 OpenAI 호환 JSON 오류를 반환하고, 재시도·능동 상태 필터·모델 폴백으로 일시적인 백엔드 장애를 격리합니다.

오류 응답 형식

라우터가 생성하는 대부분의 오류는 다음 형식입니다.

{
  "error": {
    "message": "The service is temporarily unavailable. Please try again later.",
    "type": "service_unavailable",
    "param": null,
    "code": "service_unavailable"
  }
}

네 필드는 OpenAI Error 스키마에 맞춰 항상 포함됩니다. messagetype은 문자열이고, paramcode는 값이 없으면 생략하지 않고 null로 내보냅니다.

code는 안정적인 기계 판독용 식별자이며 HTTP 상태 코드가 아닙니다. 상태 코드는 예전과 같이 HTTP 상태 줄에만 실립니다. param은 업스트림 제공자가 알려준 문제 필드 이름입니다. 속도 제한 응답에는 Retry-After가 포함될 수 있습니다.

업스트림 제공자가 자체 문자열 코드를 보내면 그 값을 그대로 전달하므로, 클라이언트는 insufficient_quotacontext_length_exceeded 같은 값으로 분기할 수 있습니다. 아래 표는 라우터가 직접 만드는 코드입니다.

라우터가 생성하는 오류 코드

코드 의미 주요 상태
invalid_request 요청이 잘못되었거나 처리할 수 없음 400
invalid_api_key 자격 증명이 없거나 유효하지 않음 401
insufficient_permissions 인증은 되었으나 해당 자원 사용 권한이 없음 403
model_not_found 라우터가 모르는 모델 404
timeout 라우터 또는 백엔드 기한 만료 408, 504
request_too_large 요청 본문이 설정된 한도를 초과함 413
rate_limit_exceeded 라우터 또는 제공자 속도 제한에 걸림 429
internal_error 라우터 설정 또는 내부 오류 500
upstream_error 백엔드가 오류로 응답했거나 스트림·연결이 실패함 502
service_unavailable 요청을 처리할 정상 백엔드가 없음 503
server_overloaded 라우터가 동시 처리 한계에 도달함 503

바이트를 보내기 전에 발생한 스트리밍 오류는 HTTP 오류 응답을 사용합니다. SSE 응답이 시작된 뒤에는 상태 코드를 바꿀 수 없으므로 스트림이 오류 이벤트를 보고하고 종료됩니다. Chat Completions 와이어에서는 오류 이벤트가 HTTP 본문과 같은 error 객체를 싣습니다. Responses 와이어에서는 평평한 ResponseErrorEvent 형태로 code, message, param, sequence_numbertype 옆에 놓입니다.

상태 코드

상태 일반적인 원인 재시도 지침
400 잘못된 요청 또는 제공자가 매개변수를 거부함 요청 수정
401 자격 증명이 없거나 유효하지 않음 인증 수정
403 인증된 호출자에게 요청 자원 권한이 없음 권한 또는 키 정책 수정
404 모델 또는 저장된 응답을 찾을 수 없음 식별자 확인
408 라우터 요청 기한 만료 작업이 안전할 때만 재시도
413 요청 본문이 설정된 한도를 초과함 요청 크기 축소
429 라우터/제공자 속도 제한 또는 할당량 소진 Retry-After 준수; 할당량 오류는 자동 재시도하지 않음
500 라우터 설정 또는 내부 오류 로그와 설정 확인
502 백엔드 연결, 스트림 또는 게이트웨이 오류 일반적으로 일시적
503 백엔드를 사용할 수 없거나 적격 백엔드가 모두 비정상 일반적으로 일시적
504 백엔드 시간 초과 일반적으로 일시적

가능한 경우 제공자 오류 본문을 정규화합니다. 인식하지 못한 제공자 4xx 응답은 길이가 제한된 메시지 일부만 유지하며 임의의 내부 데이터를 노출하지 않습니다.

재시도

최상위 retry 섹션은 선택한 백엔드에 대한 재시도를 제어합니다.

retry:
  max_attempts: 3
  initial_delay: 100ms
  max_delay: 10s
  backoff_multiplier: 2.0
  jitter: true
  retryable_status_codes: [429, 502, 503, 504]
  retryable_errors: [ConnectionError, TimeoutError]
  timeout: 30s

위 값은 기본값이기도 합니다. 라우터는 선택적으로 지터를 더한 지수 백오프를 적용합니다. 제공자 429는 일시적인 속도 제한으로 분류될 때만 재시도하며, 할당량·크레딧·결제 소진은 즉시 실패합니다. 업스트림 Retry-After 또는 Google 재시도 지연 힌트는 검증 후 적용하며 최대 24시간으로 제한합니다.

재시도는 백엔드에 대한 시도를 반복합니다. 적격 오류 뒤에 다른 모델이나 제공자를 선택할 수 있는 폴백과는 다릅니다.

서킷 브레이커

Continuum Router에는 설정 가능한 3상태 서킷 브레이커 구현과 Admin 제어 기능이 있습니다.

circuit_breaker:
  enabled: true
  failure_threshold: 5
  failure_rate_threshold: 0.5
  minimum_requests: 10
  timeout: 60s
  half_open_max_requests: 3
  half_open_success_threshold: 2
  failure_status_codes: [500, 502, 503, 504]
  timeout_as_failure: true
  sliding_window_size: 60s
  sliding_window_type: count_based
  backends:
    openai:
      failure_threshold: 10
      timeout: 120s

sliding_window_typecount_based 또는 time_based를 사용합니다. circuit_breaker.backends 항목은 지원되는 백엔드별 필드만 덮어씁니다.

일반 LLM 프록시 경로는 요청 결과를 이 상태 머신에 기록하고 백엔드 선택 시 상태를 조회합니다. 열린 백엔드 서킷은 선택에서 제외되며, 호환되는 모든 서킷이 열리면 라우터는 503 service-unavailable 오류를 반환하고 설정된 폴백에 참여합니다. 능동 상태 확인, 재시도, 폴백을 대체하지 않고 보완합니다. 결과 기록과 허용 판단의 세부 사항은 서킷 브레이커를 참고하십시오.

Admin API 인증이 허용하는 경우 다음 엔드포인트에서 상태를 확인하거나 제어할 수 있습니다.

메서드 경로 용도
GET /admin/circuit/all 모든 서킷 상태 조회
GET /admin/circuit/{backend}/status 단일 백엔드 상태 조회
POST /admin/circuit/{backend}/open 서킷 강제 열기
POST /admin/circuit/{backend}/close 서킷 강제 닫기
POST /admin/circuit/{backend}/reset 추적 중인 서킷 상태 초기화

인증과 전체 엔드포인트 설명은 Admin API를 참고하십시오.

모델 폴백

폴백 체인은 설정된 오류 조건 뒤에 대체 모델을 선택합니다.

fallback:
  enabled: true
  mid_stream_enabled: true
  fallback_chains:
    gpt-5.4:
      - gpt-5.4-mini
      - claude-sonnet-4-6
  fallback_policy:
    trigger_conditions:
      error_codes: [429, 500, 502, 503, 504]
      timeout: true
      connection_error: true
      model_not_found: true
      backend_unhealthy: true
    max_fallback_attempts: 3
    fallback_timeout_multiplier: 1.5
    preserve_parameters: true
  model_settings:
    gpt-5.4:
      fallback_enabled: true
      notify_on_fallback: true

notify_on_fallback: true(기본값)이면 성공한 폴백 응답에 다음 헤더가 포함될 수 있습니다.

  • X-Fallback-Used
  • X-Original-Model
  • X-Fallback-Model
  • X-Fallback-Reason
  • X-Fallback-Attempts — 기본 시도를 포함한 전체 모델 시도 횟수. 폴백이 응답을 만든 경우 항상 2 이상입니다.

모델에 notify_on_fallback: false를 지정하면 폴백 응답은 그대로 제공하면서 이 헤더들을 억제합니다.

체인은 요청된 모델로 백엔드를 고르는 모든 인그레스에서 실행됩니다. OpenAI 형태의 경로는 공용 디스패치 funnel을 통해, /anthropic/v1/messages/v1/responses는 자체 시도별 선택과 네이티브 디스패치를 통해 실행되며, 비스트리밍 arm과 첫 SSE 바이트 전의 스트리밍 arm 모두에 적용됩니다. 핸드셰이크가 성공한 스트리밍 시도는 확정되어 홉하지 않습니다. 체인이 소진되었거나 실패가 트리거가 아닐 때의 오류는 마지막 시도의 것이며, 해당 인그레스의 형식을 따릅니다. /anthropic/v1/messages에서는 Anthropic {"type":"error",...} 본문, /v1/responses에서는 OpenAI {"error":{...}} 본문입니다. /v1/responses/compactcount_tokens는 체인을 실행하지 않습니다. 인그레스별 규칙은 모델 폴백을 참고하세요.

제공자 간 폴백 홉은 요청 페이로드를 표준 형태 그대로 유지하며 모델 이름만 바꿉니다. 새로 선택된 백엔드에 맞춘 와이어 형식 변환은 홉이 아니라 디스패치에서 수행합니다.

fallback_timeout_multiplier(1.0–5.0, 기본값 1.5)는 각 홉이 자신의 요청 타임아웃을 얼마나 늘려 잡는지를 정합니다. 기본 시도는 설정이 해석한 타임아웃을 그대로 쓰고, 홉 nbase * multiplier^(n-1)로 동작하며 해당 타임아웃 종류의 timeouts.limits 상한으로 클램프됩니다. 기준값은 체인이 없었다면 그 시도가 사용했을 값이므로, 모델별로 길게 잡아 둔 예산은 홉에서도 길게 유지됩니다. timeouts.connection, 폴백 다이얼 퍼밋 대기, 홉 내부 재시도, 클라이언트가 이미 스트림을 받고 있는 상태에서의 스트림 중간 홉에는 적용되지 않습니다. 스트리밍 요청의 모든 시도가 공유하는 단일 벽시계 예산을 정하는 timeouts.streaming_fallback_budget_multiplier와는 다른 설정이며, 스트리밍 홉은 먼저 스케일된 뒤 그 예산의 남은 분량으로 다시 상한이 걸리므로 두 값은 함께 적용됩니다.

mid_stream_enabled: true는 스트리밍 경로가 지원하는 경우 스트림 중간 복구를 허용합니다. 출력 버퍼링이 발생할 수 있으므로 스트림 시작 뒤 복구보다 즉시 토큰 전달이 중요하면 비활성화하십시오.

시간 초과와 요청 크기

timeouts 섹션에서 라우터 및 모델 기한을 설정하고, 문서화된 서버/백엔드 섹션에서 요청 제한을 설정하십시오. 재시도 시간 제한을 호출자의 전체 기한보다 길게 두면 호출자가 연결을 끊은 뒤에도 재시도 작업이 계속될 수 있습니다.

생성된 설정을 필드의 기준 자료로 사용하십시오.

continuum-router --generate-config > config.yaml
continuum-router config validate config.yaml

관측 및 진단

문서에 없는 디버그 엔드포인트 대신 실제 구현된 인터페이스를 사용하십시오.

# 공개 프로세스/백엔드 상태
curl http://localhost:8080/health

# Admin 상태와 서킷 상태(설정한 Admin 자격 증명 추가)
curl http://localhost:8080/admin/health
curl http://localhost:8080/admin/circuit/all

# 서버를 시작하지 않고 설정 검증
continuum-router config validate /etc/continuum-router/config.yaml

metrics 기능과 런타임 메트릭 설정이 활성화되면 설정된 메트릭 경로에서 Prometheus 메트릭을 제공합니다. 로그는 tracing을 사용하며 logging.level, CONTINUUM_LOG_LEVEL 또는 RUST_LOG로 상세도를 선택할 수 있습니다.

라우터는 /admin/errors/* 또는 /admin/debug/error 엔드포인트를 제공하지 않습니다. 대신 구조화 로그, 메트릭, /admin/health, /admin/circuit/*를 확인하십시오.

클라이언트 권장 사항

  1. 예상 라우터/백엔드 시간 초과보다 긴 클라이언트 기한을 설정합니다.
  2. 애플리케이션에 중복 제거가 없다면 멱등 작업만 재시도합니다.
  3. 지터가 있는 지수 백오프를 사용하고 Retry-After를 준수합니다.
  4. 인증, 권한, 검증, 할당량 소진 오류는 요청이나 자격 증명을 바꾸지 않은 채 재시도하지 않습니다.
  5. 자체 클라이언트 로그에 상관관계/요청 식별자를 기록하고 API 키나 해석된 설정 출력을 로그에 남기지 않습니다.