오류 코드
코드별 의미 · 원인 · AI가 할 일
오류 코드 직접 확인하기펼쳐보기
요청 헤더 XenoCI-Error-Format: 2를 보내면 4xx·5xx 응답 본문이 아래 봉투입니다. 헤더가 없으면 하위 호환으로 error는 코드 문자열이고 같은 내용이 error_detail에 들어 있습니다.
next에는 다음에 할 요청이 들어 있고, request_id는 응답 헤더 X-Request-Id와 같습니다. fault가 platform인 오류는 XenoCI에 자동으로 보고되어 우리가 고칩니다.
{
"error": {
"code": "no_capacity",
"message": "No Mac of this product is free now",
"retryable": true,
"retry_after_s": null,
"fault": "capacity",
"next": [
{
"action": "join_waitlist",
"method": "POST",
"path": "/api/ci/v1/waitlist",
"body": {
"tier": "<tier>",
"units": 1
}
}
],
"docs": "https://xenoci.com/docs/errors#no_capacity",
"request_id": "req_…"
}
}fault: client 요청을 고침 · capacity 지금 자리가 없음 · payment 사람이 결제·동의해야 함 · platform 우리 쪽 문제.
빌드 실패(failure)
실패한 빌드의 GET /builds/{id}에는 failure가 붙습니다: fault(customer 사용자 코드 · platform 우리 쪽 · unknown), reason_code(예: compile_error, xcodebuild_failed), summary, suggestion, log_excerpt_lines(전체 로그의 1부터 세는 줄 범위), location(파일·줄·메시지). customer면 그 줄을 고쳐 다시 빌드하고, platform이면 코드를 그대로 두고 다시 빌드합니다. 실패한 빌드와 API 오류는 GET /errors?kind=build&fault=platform처럼 다시 볼 수 있습니다.
| 코드 | HTTP | fault | 재시도 | 의미 | AI가 할 일 |
|---|---|---|---|---|---|
api_key_required | 401 | client | 아니요 | Authorization 헤더가 없거나 형식이 틀림 | Authorization: Bearer xeno_ci_… 헤더를 붙임. 키가 없으면 사람에게 /app/api-keys 에서 만들어 달라고 요청 |
invalid_api_key | 401 | client | 아니요 | 없는·폐기된·만료된 키이거나 계정이 비활성 | 사람에게 새 키를 받아 달라고 요청 |
organization_suspended | 403 | client | 아니요 | 계정 정지 | 멈추고 사람에게 알림 |
ip_not_allowed | 403 | client | 아니요 | 키에 허용된 IP(CIDR) 밖에서 호출 | 허용된 곳에서 호출하거나 사람에게 키의 허용 IP 변경을 요청 |
insufficient_scope | 403 | client | 아니요 | 키에 이 요청 권한이 없음. error_detail.required_level(read·build·manage), required_scope, key_levels 포함 | 사람에게 required_level 권한이 켜진 키를 요청 |
forbidden | 403 | client | 아니요 | 그 밖의 권한 없음 | 키와 계정을 확인. 재시도하지 않음 |
api_key_read_only | 403 | client | 아니요 | 읽기 전용 키로 쓰기 요청 | build·order 권한이 있는 키를 사용 |
api_key_write_only | 403 | client | 아니요 | 쓰기 전용 키로 읽기 요청 | read 권한이 있는 키를 사용 |
organization_required | 403 | client | 아니요 | 키가 계정에 연결되어 있지 않음 | 사람에게 키를 다시 만들어 달라고 요청 |
account_blocked | 403 | payment | 아니요 | 결제 분쟁 등으로 계정의 결제가 막힘 | 멈추고 사람에게 알림 |
rate_limited | 429 | client | 예 | 1분 요청 수 한도 초과. retry_after_s 포함 | retry_after_s(또는 Retry-After)만큼 기다린 뒤 같은 요청 |
too_many_pending_orders | 429 | client | 예 | 이 키의 결제 대기 주문 수 한도 | GET /orders?status=awaiting_payment 로 기존 주문을 확인해 결제를 요청하거나 결제 링크가 만료되기를 기다림 |
too_many_concurrent_builds | 429 | client | 예 | 이 키의 동시 빌드 수 한도 | GET /builds?state=running 으로 확인하고 끝나기를 기다린 뒤 다시 제출 |
queue_full | 429 | capacity | 예 | 계정 빌드 대기열이 가득 참 | GET /builds?state=queued 로 확인하고 진행 중인 빌드가 끝난 뒤 다시 제출 |
no_capacity | 409 | capacity | 예 | 고른 상품에 지금 빈 맥이 없음 | next의 POST /waitlist로 재입고 알림을 신청하거나 catalog에서 다른 상품을 고름 |
sales_closed | 409 | capacity | 예 | 지금은 판매를 받지 않음 | GET /catalog 로 sales_open을 다시 확인하고 사람에게 알림 |
available_now | 409 | client | 아니요 | 재고가 있어 재입고 알림 대신 바로 주문할 수 있음 | POST /orders 로 주문 |
waitlist_exists | 409 | client | 아니요 | 같은 상품 재입고 알림이 이미 있음 | 그대로 둠(GET /waitlist) |
order_not_found | 404 | client | 아니요 | 없는 주문이거나 다른 계정의 주문 | GET /orders 로 번호 확인 |
order_expired | 409 | client | 아니요 | 결제 링크나 자리 보류가 만료됨 | POST /orders 로 새로 주문하고 새 pay_url을 사람에게 보여 줌 |
order_not_payable | 409 | client | 아니요 | 이미 결제되었거나 취소된 주문 | GET /orders/{order_no} 로 상태 확인 |
payment_mismatch | 400 | payment | 아니요 | 결제 검증 불일치(결제 화면 전용) | 사람에게 알림 |
consent_required | 400 | client | 아니요 | 사람의 동의가 없음(결제 화면 전용, API 주문에서는 나오지 않음) | pay_url을 사람에게 보여 줌. 동의는 사람이 결제 화면에서 함 |
rental_not_found | 404 | client | 아니요 | 없는 맥이거나 다른 계정의 맥 | GET /rentals 로 ID 확인 |
rental_not_active | 409 | client | 아니요 | 맥이 사용 중 상태가 아님 | GET /rentals/{id} 로 상태 확인 |
extension_deadline | 409 | client | 아니요 | 종료 10분 전이 지나 연장할 수 없음 | 새 맥을 주문하고 빌드를 옮김 |
extension_pending | 409 | client | 예 | 같은 맥의 연장 결제가 진행 중 | GET /orders?status=awaiting_payment 의 pay_url을 사람에게 다시 보여 줌 |
extension_unavailable | 409 | client | 아니요 | 일괄 연장 중 연장할 수 없는 맥이 있음(items에 맥별 reason) | POST /rentals/extend/quote 로 확인하고 가능한 맥만 다시 주문 |
rental_duration_limit | 422 | client | 아니요 | 같은 맥 30일 상한을 넘김 | hours를 줄이거나(max_extend_days) 새 맥을 주문 |
reservation_conflict | 409 | capacity | 아니요 | 다음 예약과 겹침 | hours를 줄이거나 다른 맥을 주문 |
invalid_period | 422 | client | 아니요 | hours가 24의 배수가 아니거나 범위를 벗어남 | GET /catalog 의 기간 규칙대로 24, 48, 72 … |
invalid_tier | 400 | client | 아니요 | 주문·견적 입력 오류(invalid_setup, invalid_quote, invalid_order, invalid_start, invalid_hours, invalid_rentals도 같음) | GET /catalog 를 보고 입력을 고침 |
no_active_rental | 409 | client | 아니요 | 빌드할 맥이 없음 | GET /catalog → POST /orders 로 맥을 빌리거나, queue_until_rental: true 로 빌드를 대기시킴 |
build_not_found | 404 | client | 아니요 | 없는 빌드이거나 다른 계정의 빌드 | GET /builds 로 ID 확인 |
build_not_queued | 409 | client | 아니요 | 대기 중인 빌드가 아님(우선순위 변경 불가) | 그대로 둠 |
invalid_script | 400 | client | 아니요 | 빌드 입력 오류(invalid_build, invalid_xcode, one_source_only, invalid_repo_url, repo_host_not_allowed, invalid_ref 등도 같음) | 입력을 고쳐 다시 제출. xcode는 catalog의 목록에서 |
upload_incomplete | 409 | client | 예 | 업로드한 파일이 아직 다 오지 않음 | GET /uploads/{id} 로 빠진 파일을 보내고 다시 제출 |
upload_not_found | 404 | client | 아니요 | 업로드가 없거나 만료됨 | 폴더를 다시 업로드(build 도구는 자동) |
uploads_unavailable | 503 | platform | 예 | 업로드 저장소 문제(우리 쪽) | retry_after_s 뒤에 다시 |
gzip_required | 415 | client | 아니요 | 업로드는 gzip이어야 함 | Content-Type: application/gzip |
manifest_too_large | 413 | client | 아니요 | 업로드 매니페스트가 너무 큼 | .gitignore로 파일 수를 줄임 |
upload_too_large | 400 | client | 아니요 | 업로드 입력 오류(invalid_gzip, invalid_manifest, invalid_tar, too_many_files, empty_upload 등도 같음) | .gitignore로 빌드 산출물·의존성 폴더를 빼고 다시 업로드 |
blob_not_in_manifest | 409 | client | 아니요 | 매니페스트에 없는 파일을 보냄 | 업로드를 처음부터 다시 |
invalid_offset | 400 | client | 아니요 | 조회 파라미터 오류(invalid_wait, invalid_timeout, invalid_time, invalid_from, invalid_to도 같음) | 파라미터를 고침 |
invalid_secret_name | 400 | client | 아니요 | 시크릿 입력 오류(invalid_secret_value, secrets_limit도 같음) | 이름은 대문자·숫자·_ (예: MATCH_PASSWORD) |
secret_not_found | 404 | client | 아니요 | 그런 이름의 시크릿이 없음 | GET /secrets 로 이름 확인 |
waitlist_not_found | 404 | client | 아니요 | 재입고 알림 신청이 없음 | GET /waitlist 로 ID 확인 |
waitlist_not_cancellable | 409 | client | 아니요 | 이미 처리된 재입고 알림 | 그대로 둠 |
invalid_waitlist | 400 | client | 아니요 | 재입고 알림 입력 오류 | GET /catalog 의 tier로 다시 |
reset_limit | 429 | client | 예 | VM 재설정(새 VM)은 10분에 1번, 하루 20번까지 | 잠시 뒤 다시 하거나 keep_cache: true(작업 폴더만 비움)로 진행 |
job_in_progress | 409 | client | 예 | 이 Mac에 리셋·Xcode·설정 작업이 이미 대기 중이거나 진행 중. error_detail.job_id | next의 GET /jobs/{job_id}가 done·failed가 된 뒤 다시 |
job_not_found | 404 | client | 아니요 | 이 계정에 그런 작업이 없음 | job_id 확인(op_…) |
invalid_setup | 400 | client | 아니요 | 카탈로그에 없는 Xcode·runtimes·tools 값, 또는 바꿀 값이 없음. error_detail.field, options | options 중에서 다시 |
invalid_target | 400 | client | 아니요 | all: true와 ids 중 하나만 보내야 함 | 둘 중 하나로 다시 |
invalid_when | 400 | client | 아니요 | when은 after_build 또는 now | 둘 중 하나로 다시 |
invalid_idempotency_key | 400 | client | 아니요 | Idempotency-Key는 보이는 ASCII 1~200자 | 새 키로 다시 |
idempotency_conflict | 409 | client | 아니요 | 같은 Idempotency-Key를 다른 요청에 썼음 | 새 키로 다시. 같은 요청을 다시 보내면 첫 응답이 그대로 옴(Idempotent-Replayed: true) |
xcode_not_available | 400 | client | 아니요 | 이 맥 등급에서 고를 수 없는 Xcode 버전. error_detail.options에 고를 수 있는 목록 | options 중 하나로 다시 |
endpoint_removed | 410 | client | 아니요 | 없어진 엔드포인트(결제 전 주문 취소 등) | 결제하지 않은 주문은 결제 링크가 만료되면 자동으로 풀림. 그대로 둠 |
reset_failed | 409 | platform | 예 | 맥 초기화 실패(우리 쪽) | 잠시 뒤 다시. 자동으로 XenoCI에 보고됨 |
rental_busy | 409 | client | 예 | 빌드 실행 중이라 바로 Xcode 변경·재설정을 할 수 없음 | when: "after_build"(빌드가 끝난 뒤) 또는 when: "now"(빌드를 취소하고 바로)를 붙여 다시 |
rental_only | 410 | client | 아니요 | /jobs는 폐기됨 | POST /builds 사용 |
internal_error | 500 | platform | 예 | 우리 쪽 오류. 자동으로 XenoCI에 보고됨 | 잠시 뒤 같은 요청을 한 번 재시도. 계속되면 request_id를 사람에게 전달 |