# v0 에러 코드/메시지 표준 — File Time Search MCP
본 문서는 `fs.search_by_time` 도구의 **tool 실행 에러(`isError=true`)** 에서 사용할 에러 코드와 메시지 템플릿을 표준화합니다.
주의:
- MCP 프로토콜 에러(JSON-RPC error)는 “요청 구조 자체 문제(unknown tool, malformed request 등)”에만 사용한다.
- 이 문서는 **tool 실행 에러(isError=true)** 만 다룬다.
참조:
- [PRD-API.md](PRD-API.md)
- [PRD-v0-Policy.md](PRD-v0-Policy.md)
---
## 1) 에러 메시지 템플릿(v0)
tool 실행 에러는 아래 형식을 권장한다.
- `content[0].type = "text"`
- `content[0].text`는 LLM이 수정해서 재시도하기 쉬운 문장으로 구성
권장 포맷(3줄):
1) `ErrorCode: <CODE>`
2) `Message: <한 문장 설명>`
3) `Fix: <사용자가 바꿔야 할 입력 가이드>`
예:
```
ErrorCode: InvalidRange
Message: 'from' must not be later than 'to'.
Fix: Set 'from' <= 'to' (from inclusive, to exclusive).
```
추가로, 디버깅에 도움이 되는 정보는 4번째 줄 이후에 선택적으로 포함할 수 있다.
- 단, allowed root의 절대 경로 목록처럼 민감/노출이 큰 정보는 포함하지 않는다.
---
## 2) 표준 에러 코드 목록(v0)
### 2.1 입력 검증(Validation)
| Code | 발생 조건 | Fix(요지) |
|---|---|---|
| `InvalidDateTime` | `from` 또는 `to`가 ISO 8601 date-time 형식이 아님 | `2025-12-15T00:00:00Z` 같은 값 사용 |
| `InvalidRange` | `from > to` | `from <= to`로 조정 (`from == to`는 유효하며 결과 0개) |
| `InvalidEnum` | `timeField`/`sort` 등 enum 값이 스펙과 다름 | 허용 enum 값으로 수정 |
| `LimitOutOfRange` | `limit < 1` 또는 `limit > 1000` | `1..1000` 범위로 수정 |
| `GlobTooLong` | `glob` 길이 제한 초과 | 패턴을 단순화 |
| `PathTooLong` | `path` 길이 제한 초과 | 시작 경로를 단순화 |
| `CursorTooLong` | `cursor` 길이 제한 초과 | 커서를 그대로 전달했는지 확인 |
| `MaxDepthOutOfRange` | `maxDepth < 0` 또는 서버 상한 초과 | 0 이상, 상한 이하로 조정 |
### 2.2 보안/권한(Security)
| Code | 발생 조건 | Fix(요지) |
|---|---|---|
| `RootNotAllowed` | 요청 `root`가 허용 루트가 아님 | 허용된 루트로 재시도 또는 root 생략 |
| `PathNotRelative` | `path`가 절대 경로/UNC/드라이브 경로 | `root` 기준 상대 경로로 변경 |
| `PathTraversalDetected` | 정규화 후 루트 탈출(`..` 등) | `..` 제거, 루트 내부로 제한 |
| `SymlinkEscapeDetected` | 링크/리파스 포인트 추적 시 루트 밖으로 이탈 | 링크를 제거하거나 루트 내로 제한 |
| `AccessDenied` | 권한 부족으로 디렉터리/파일 접근 불가(정책상 실패 처리 선택 시) | 권한 있는 루트/경로로 변경 |
권장(LLM/에이전트 친화):
- 단일 파일/디렉터리에서 발생한 권한 오류는 “부분 스킵”으로 처리하고, 전체 요청 실패는 최소화한다.
- 단, `root` 자체 접근 불가 등 “요청 전체가 무의미”한 케이스는 `AccessDenied`로 실패해도 된다.
### 2.3 커서(Cursor)
| Code | 발생 조건 | Fix(요지) |
|---|---|---|
| `CursorInvalid` | base64url 디코딩 실패, JSON 파싱 실패, 필드 누락 | 첫 페이지(cursor 생략)부터 재시도 |
| `CursorVersionMismatch` | 커서 `v`가 지원되지 않음 | cursor 생략 후 재시도 |
| `CursorSortMismatch` | 요청 `sort`와 커서에 기록된 `sort`가 다름 | 이전과 동일한 sort로 재시도 |
### 2.4 스캔 제한/타임아웃(Limits)
| Code | 발생 조건 | Fix(요지) |
|---|---|---|
| `ScanLimitExceeded` | `maxFilesScanned` 또는 `maxDirectoriesScanned` 도달, 그리고 `nextCursor` 생성 불가 | 더 좁은 `path`/`glob`/범위로 재시도 |
| `TimeoutExceeded` | `timeoutMs` 도달, 그리고 `nextCursor` 생성 불가 | 더 좁은 조건으로 재시도 |
참고:
- v0 기본 정책은 “부분 결과 + nextCursor”를 우선한다([PRD-v0-Policy.md](PRD-v0-Policy.md) 7장).
- 위 코드들은 “부분 결과도 만들 수 없는 상황”에서의 실패에 사용한다.
### 2.5 내부 오류(Internal)
| Code | 발생 조건 | Fix(요지) |
|---|---|---|
| `IOFailure` | 예기치 않은 I/O 예외로 처리 불가 | 잠시 후 재시도, 또는 범위를 축소 |
---
## 3) 프로토콜 에러와의 경계(요약)
다음은 tool 실행 에러가 아니라 **프로토콜 에러(JSON-RPC error)** 로 처리한다.
- Unknown tool name
- CallToolRequest 자체가 스키마를 만족하지 못하는 malformed request
- 서버가 응답 프레임을 만들 수 없을 정도의 치명적 예외
---
## 4) 변경 이력
- v0: 최초 고정