---
title: "자동화 오류 해결"
description: "Alpacon 자동화 작업의 실패 원인을 HTTP 상태와 오류 코드, 명령어 결과로 확인합니다. 토큰 승인, scope, 요청 수 제한, 계정과 ACL, sudo 문제를 구분하고 CI 작업을 다시 실행하기 전에 필요한 권한과 설정을 순서대로 점검하는 방법을 안내합니다."
---

> Full documentation index: https://docs.alpacax.com/llms.ko.txt

# 자동화 오류 해결

먼저 HTTP 상태와 `code`를 확인하고, 요청이 접수되었다면 명령어 결과를 확인하세요. 코드가 있는 API 오류에는 `code`가 포함되고, 입력 검증 오류에는 `field_errors`도 포함될 수 있습니다. 일부 거부 응답에는 `gate`와 `missing`이 있지만 모든 오류에 있는 것은 아닙니다. 설정 절차는 [서비스 토큰](/use/iam/applications/service-tokens/), 연결 옵션은 [Ansible](/integrate/ansible/)을 참고하세요.

## 이전 CLI에서 로그인 중 401 발생

v1.7.4보다 오래된 CLI는 로그인 시 `alpst-` 키를 받아들인 뒤 사용자 프로필 확인에 실패할 수 있습니다. 요청은 `401 auth_token_missing`을 반환하며 이전 CLI는 다음 메시지를 출력합니다.

```text
Login succeeded but failed to verify user profile: request denied by server. Please try logging in again.
```

Alpacon CLI v1.7.4 이상을 사용하고 작업 컨테이너나 러너 안의 버전을 확인하세요. 키는 `alpacon login ... -t "$ALPACON_SERVICE_TOKEN"`으로 전달합니다. CLI는 `ALPACON_URL`이나 `ALPACON_TOKEN`을 읽지 않습니다. 이 환경 변수는 Ansible 연결에 사용합니다.

## 토큰 승인 대기 중 202 발생

승인이 필요한 서비스 토큰을 생성하면 `202`가 반환됩니다. 응답에는 `key`, `status: "pending_approval"`, `risk_level`, `risk_details`(각 항목에 `scope`, `reason`, `level` 포함), `approval_request_id`가 있습니다. 이때 받은 키는 아직 사용할 수 없으며 승인 전까지 `401 auth_authentication_failed`가 반환됩니다.

admin 역할이 있는 계정이 웹 콘솔에서 위험도가 낮은 scope를 요청한 경우에만 즉시 활성화됩니다. 명령어와 파일 전송 scope는 항상 승인을 기다립니다. 웹 콘솔에서 슈퍼유저나 해당 요청의 승인자에게 승인을 요청하세요. 작업을 시작하기 전에 `GET /api/auth/service-tokens/tokens/{id}/`에서 `activation_state: "active"`와 `enabled: true`를 확인하세요.

보안 설정 변경도 `status`, `risk_level`, `risk_details`, `approval_request_id`가 포함된 `202`를 반환하지만 키는 포함하지 않습니다. 승인 전까지 기존 설정이 적용됩니다. 다른 변경이 이미 승인 대기 중이면 `400 service_token_update_pending`이 반환되므로 먼저 기존 요청을 처리하거나 취소하세요.

사람의 승인을 기다리는 명령어는 명령어 기록에 `status: "awaiting_approval"`로 표시됩니다. 토큰 생성의 `202`와는 다릅니다. 웹 콘솔에서 기존 명령어를 검토하세요.

## 권한 부족으로 403 발생

토큰에 scope가 없으면 다음 응답을 받을 수 있습니다.

```json
{
  "code": "api_token_scope_missing",
  "gate": "token_scope",
  "missing": "scope:command:create"
}
```

`missing`은 문자열 하나 또는 목록입니다. scope나 `role`, `command_preapproval`, `approval`, `presence`, `work_session`, `plan`, `approved_account`, `other_approver`, `allowed_agent` 등의 조건을 나타냅니다. 위 예시에서 CLI는 `permission denied: missing scope scope:command:create`를 출력합니다.

애플리케이션의 전역 역할과 토큰이 모두 해당 작업을 허용하는지 확인하세요. 필요한 토큰 scope 변경을 요청하고 승인을 기다리세요. 역할 때문에 거부되면 `rbac_permission_required` 또는 `rbac_object_permission_required`와 함께 `gate: "role"`, `missing: "role"`이 반환됩니다. CLI에는 `permission denied: missing role`이 표시됩니다. 관리자에게 역할 부여 상태를 확인해 달라고 요청하세요. scope를 추가해도 계정, 승인, presence 조건이 충족되지는 않습니다.

## 요청 수 초과로 429 발생

서비스 토큰의 요청 수 제한을 넘으면 `429`와 함께 다음 응답이 반환됩니다.

```json
{"code": "api_rate_limited", "gate": "rate"}
```

`Retry-After` 헤더는 재시도 전 기다릴 시간을 초 단위로 알려 줍니다. 제한은 토큰별로 적용되며 별도로 설정하지 않으면 `1000/hour`입니다. 안내된 시간 이상 기다린 뒤 재시도하고, 동시에 실행하는 조회나 작업 요청을 줄이세요. 토큰의 요청 수 제한을 변경하려면 승인이 필요합니다.

CLI는 `too many requests—please try again later`를 출력하고 상태 조회 간격을 늘립니다. Ansible은 HTTP 429 오류를 즉시 반환하므로 작업에서 재시도를 처리해야 합니다. 플랜의 월간 한도를 넘으면 `429`가 아닌 `402`가 반환되며 이때도 `Retry-After`가 포함됩니다.

## sudo 거부

Alpacon Cloud에서는 서비스 토큰의 sudo 위험도가 심각(Critical)보다 낮거나 평가되지 않았으면 허용하고, 심각이면 거부합니다. 단, Advisory 워크스페이스에서는 위험도를 이유로 거부하지 않고 판단을 기록합니다. Advisory가 아니면 워크스페이스의 `token_exec` 규칙으로 위험도 기준을 더 엄격하게 정할 수 있습니다. 워크스페이스의 sudo 설정도 켜져 있어야 하며, 꺼져 있으면 `workspace_sudo_with_mfa_disabled`로 거부됩니다. 위험도에 따른 거부 코드는 `sudo_risk_denied`입니다. 전달 전에 명령어 전체가 거절되면 상태가 `rejected`가 됩니다. 명령어 상세에서 `rejection_cause`, `rejection_gate`, `rejected_at`을 확인하세요. Ansible은 `rc: 1`을 반환하고 stderr에 `rejected`를 출력합니다. 명령어는 실행되었지만 sudo에서 실패했다면 출력과 [권한 상승](/use/audit/events/sudo/)의 **거부** 탭을 확인하세요.

CLI의 위험도 거부 안내는 `sudo was denied by runtime risk assessment; this command is not permitted in this work session.`입니다. 토큰 명령어에도 같은 문구를 사용합니다. 거부된 작업을 검토하고 애플리케이션이 실행할 수 있는 더 좁은 범위의 명령어를 사용하세요.

기본 설정의 자체 호스팅에서는 위험도와 관계없이 모든 서비스 토큰 sudo가 `sudo_command_not_authorized`로 거부됩니다. CLI는 이 배포 환경에서 서비스 토큰의 권한을 높일 수 없다고 안내합니다. Ansible은 토큰만 사용하므로 기본 설정의 자체 호스팅에서는 `become`을 사용할 수 없습니다. sudo 정책은 서비스 토큰에 적용되지 않으며 재시도해도 사람에게 sudo 승인 요청이 생성되지 않습니다.

## 토큰 만료나 키 교체 후 401 발생

만료된 서비스 토큰은 `401`, `{"code": "auth_authentication_failed"}`, `WWW-Authenticate: Token`을 반환합니다. 잘못된 키, 비활성화·승인 대기·삭제된 토큰, 애플리케이션이 삭제된 토큰도 같은 응답을 받습니다. 응답만으로는 원인을 구분할 수 없습니다. CLI는 `authentication failed: please run 'alpacon login' again`을 출력합니다.

웹 콘솔에서 토큰 상태와 만료일을 확인하세요. 만료된 토큰이라면 새 토큰을 발급하고 승인을 받은 뒤 CI 시크릿을 갱신하고 재시도하세요. 키를 교체했다면 CI 시크릿도 즉시 갱신해야 합니다. 교체가 끝나는 순간 기존 키는 무효화됩니다. 만료일은 현재 시점에 교체 주기(기본 90일)를 더한 날짜로 다시 설정되므로 새 날짜도 확인하세요. 비활성화된 토큰은 다시 활성화할 때 승인이 필요합니다. 승인 대기 중이라면 승인을 마친 뒤 재시도하세요.

## IP 주소나 접근 시간 거부

`401 auth_ip_not_allowed`는 러너의 주소가 토큰의 허용 IP에 없다는 뜻입니다. `401 auth_access_outside_allowed_time`은 UTC 기준 허용 시간대나 요일을 벗어났다는 뜻입니다. CLI는 이 오류에 `request denied by server`를 출력합니다.

러너의 외부 통신 IP와 실행 일정을 토큰의 제한과 비교하세요. 다른 접근 범위가 필요하면 제한 변경을 요청하세요. 변경에는 승인이 필요합니다.

## 자격 증명 확인 불가

`503 auth_verification_unavailable`은 자격 증명이 거부된 것이 아니라 서버가 확인하지 못했다는 뜻입니다. CLI는 `the server could not verify your credential right now—it was not rejected, so try again in a moment`를 출력합니다. 잠시 뒤 재시도하세요.

## 서버 계정 오류로 400 발생

서비스 토큰은 애플리케이션이 소유한 계정으로만 실행할 수 있습니다. 입력 검증 코드와 `field_errors`를 확인하세요.

| 코드 | 원인과 조치 |
| --- | --- |
| `workspace_direct_root_disabled` | root 직접 접근이 꺼진 상태에서 `root`를 요청함. 애플리케이션 계정 사용 |
| `application_system_user_not_found` | 연결된 계정이나 프로비저닝할 애플리케이션 사용자 이름이 없음. 계정을 연결하거나, 최신 에이전트가 있는 지원 Linux 서버에서 애플리케이션 사용자 이름을 지정하고 프로비저닝 활성화 |
| `system_user_bound_under_another_name` | 연결된 계정의 이름이 다름. 연결된 계정의 이름 사용 |
| `server_username_groupname_invalid` | 선택한 계정이 애플리케이션 소유가 아님. 애플리케이션이 소유한 계정 선택 |
| `system_user_access_denied` | 계정의 로그인이 비활성화되었거나 만료됨. 관리자에게 상태 확인 요청 |

Ansible에서는 `ansible_user`를 명시하세요. 기본값인 `root`는 서비스 토큰으로 사용할 수 없습니다. ACL 규칙으로 다른 계정의 소유권을 부여할 수는 없습니다.

## 서버 연결이나 활성화 문제

단일 `server` 요청에서 대상 서버가 명령어를 받을 수 없으면 `400 server_not_connected` 또는 `400 server_not_commissioned`가 반환됩니다. 연결을 복구하거나 서버를 활성화한 뒤 재시도하세요. `servers`를 사용하는 요청은 연결이 끊긴 대상에도 대기열에 명령어를 넣을 수 있으므로, 접수되었다는 이유만으로 실행되었다고 판단하지 말고 각 명령어의 상태를 확인하세요.

## 토큰 scope가 애플리케이션 역할을 초과

요청한 scope가 애플리케이션의 전역 역할 범위를 넘으면 토큰 생성 시 `400 service_token_scope_exceeds_role`이 반환됩니다. 권한이 있는 관리자에게 필요한 전역 역할 부여를 요청하거나 scope를 줄인 뒤 토큰을 다시 요청하세요. 나중에 역할을 회수하면 남은 권한을 초과하는 토큰은 비활성화되고 다음 요청에서 `401`이 반환됩니다.

## 서버, 명령어, 파일 ACL 거부

`403 api_token_acl_not_allowed`는 접근 규칙이 작업을 허용하지 않는다는 뜻입니다. `missing` 필드는 없습니다. CLI는 `denied by token access control—this token may not perform that action; review its rules with 'alpacon token acl'`을 출력합니다.

서비스 토큰의 단일 서버 요청에서는 서버가 서버 ACL에 없거나 존재하지 않으면 `field_errors.server`에 `400 does_not_exist`가 반환될 수 있습니다. 서버 ID를 확인하고 토큰 승인 후 서버 규칙을 추가하세요. 파일 전송은 경로와 방향(업로드, 다운로드 또는 둘 다)을 허용해야 합니다.

Cloud에서는 사전 승인된 명령에 없는 명령어도 `201`로 접수된 뒤 `rejected`로 종료됩니다. 이때 `rejection_cause`는 `command_acl_denied` 또는 `command_acl_unavailable`입니다. Ansible은 이 경우에도 `Command was rejected by the approval policy`를 출력하므로 명령어 규칙이 없는 것은 아닌지 확인하세요. 자체 호스팅에서 명령어 ACL로 거부되면 `403 api_token_acl_not_allowed`가 반환됩니다. 제출한 명령어 전체 문자열이 ACL과 일치하는지 확인하세요. Cloud에서는 **명령 ACL 관리자**에 등록된 관리자에게 웹 콘솔의 서비스 토큰 페이지에서 **사전 승인된 명령**을 관리해 달라고 요청하세요. Cloud에서 API로 명령어 ACL을 변경하면 `405 command_acl_moved`가 반환되므로 CLI 안내에 나온 변경 작업을 반복해도 해결되지 않습니다.

## 명령어에 포함된 자격 증명 거부

`400 command_inline_credential`은 제출한 명령어에 자격 증명이 직접 포함되어 있다는 뜻입니다. 명령어 문자열에서 자격 증명을 제거하고 작업의 시크릿 처리 방식으로 전달한 뒤 재시도하세요.

## 대화형 작업 거부

`403 auth_interactive_channel_requires_presence`는 Websh, 터널, 브라우저 편집기 같은 대화형 작업에 토큰을 사용했다는 뜻입니다. 비대화형 명령어에는 `alpacon exec`를 사용하세요. 대화형 작업은 `-t` 없이 `alpacon login`으로 로그인해서 진행하세요.

## 워크스페이스 정지

워크스페이스가 정지된 동안 변경 요청은 `403 workspace_suspended`를 반환합니다. 작업을 다시 시도하기 전에 워크스페이스 관리자에게 정지 사유를 해결해 달라고 요청하세요.

## Ansible 설정이나 파일 전송 실패

`ALPACON_URL` 또는 `ALPACON_TOKEN`이 없으면 Ansible이 필수 옵션 오류를 표시합니다. 워크스페이스 URL과 승인된 `alpst-` 키를 설정하세요. 서버 이름이 여러 대상과 일치하면 `Multiple servers match name ...`이 표시됩니다. `alpacon_server_id`에 대상 서버 UUID를 지정하세요. 파일 전송에는 S3 기반 스토리지가 필요하므로 재시도 전에 스토리지와 토큰의 파일 ACL을 확인하세요. 전체 연결 옵션은 [Ansible](/integrate/ansible/)을 참고하세요.

Source: https://docs.alpacax.com/ko/integrate/automation-failure-modes/
