> ## Documentation Index
> Fetch the complete documentation index at: https://playwave.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 에러 코드

> Game Server API 에러 코드와 처리 방법

## 에러 응답 형식

```json theme={null}
{
  "success": false,
  "error": {
    "code": "INVALID_API_KEY",
    "message": "API Key is invalid or inactive",
    "timestamp": "2026-03-06T12:00:00.000Z"
  }
}
```

## HTTP 에러 코드

| 코드                  | HTTP | 설명                            |
| ------------------- | ---- | ----------------------------- |
| `BAD_REQUEST`       | 400  | 요청 본문 검증 실패 (필수 필드 누락, 형식 오류) |
| `INVALID_API_KEY`   | 401  | API Key 누락, 무효, 또는 비활성 게임     |
| `RATE_LIMITED`      | 429  | 요청 빈도 제한 초과                   |
| `SESSION_NOT_FOUND` | 404  | 게임 세션을 찾을 수 없음 (만료/삭제)        |
| `SESSION_ENDED`     | 410  | 게임 세션이 이미 종료됨                 |
| `SESSION_ENDING`    | 410  | 게임 세션 종료 진행 중 (유예 기간)         |
| `ALREADY_ENDED`     | 409  | 이미 종료된 세션에 대한 중복 종료 시도        |
| `INTERNAL_ERROR`    | 500  | 서버 내부 오류                      |

## 비즈니스 상태 코드

HTTP 200으로 반환되며, 응답 body의 `reason` 또는 `result` 필드로 전달됩니다.

### verify 응답 reason

| reason             | 설명                 | 게임 서버 처리          |
| ------------------ | ------------------ | ----------------- |
| `OTT_EXPIRED`      | OTT 만료 (1분 초과)     | 유저에게 런처 재실행 안내    |
| `OTT_ALREADY_USED` | OTT 이미 사용됨         | 중복 접속 방지 — 유저 킥   |
| `GAME_MISMATCH`    | OTT/API Key 게임 불일치 | 잘못된 OTT — 유저 킥    |
| `NOT_CHARGEABLE`   | 과금 불가 (G-coin 부족)  | 유저에게 G-coin 충전 안내 |

### heartbeat 응답 result

| result             | 설명                | 게임 서버 처리                  |
| ------------------ | ----------------- | ------------------------- |
| `OK`               | 정상                | 다음 하트비트까지 대기              |
| `CHARGE_EXHAUSTED` | G-coin 소진         | 유저에게 안내, 서버 2분 유예 후 자동 종료 |
| `SESSION_REPLACED` | 같은 PC에서 다른 세션 시작됨 | 하트비트 중지. 세션 종료 API 호출 불필요 |

## 에러 처리 패턴

### 재시도 가능한 에러

```lua theme={null}
-- 네트워크 에러, 5xx 에러는 다음 하트비트 주기에 재시도
if err == "NETWORK_ERROR" or string.sub(err, 1, 5) == "HTTP_5" then
    warn("[Playwave] Temporary error, will retry:", err)
    -- 다음 루프 주기에 자동 재시도
end
```

### 세션 소멸 에러

```lua theme={null}
-- 404/410 에러는 세션이 사라진 상태 — 하트비트 중지 + 유저 킥
if err == "HTTP_404" or err == "HTTP_410" then
    activeSessions[userId] = nil
    local player = Players:GetPlayerByUserId(userId)
    if player then
        player:Kick("PlayWave session expired")
    end
end
```

### 무시 가능한 에러

```lua theme={null}
-- 세션 종료 시 404/409는 이미 정리된 상태 — 무시
if err == "HTTP_404" or err == "HTTP_409" then
    -- 정상 동작 — 세션이 이미 정리됨
    return
end
```
