흔한 오류 해결하기
흔한 오류 해결하기 (common-errors)
Qdrant를 운영하다 보면 서버 로그나 API 응답에서 다양한 오류를 만나게 돼요. 대부분은 환경 설정이나 파일 시스템, 클라이언트 사용 방식에서 비롯되기 때문에, 어떤 상황에서 이 오류가 나오고 어떻게 풀어야 하는지 하나씩 짚어볼게요.
출처: Qdrant 공식문서
열 수 있는 파일이 너무 많음 (OS error 24)
컬렉션의 각 세그먼트(search segment)는 몇 개의 파일을 열어야 동작해요. 그러다 보면 어느 순간 서버 로그에서 이런 오류를 마주치게 됩니다.
Error: Too many files open (OS error 24)
이럴 때는 열 수 있는 파일의 개수 제한을 늘려주면 돼요. 예를 들어 Docker 컨테이너를 실행하면서 설정할 수 있습니다.
docker run --ulimit nofile = 10000:10000 qdrant/qdrant:latest
위 명령은 소프트(soft) 한도와 하드(hard) 한도를 모두 10000으로 설정해요. Docker를 쓰지 않는다면, 아래 명령으로 현재 사용자 세션의 제한을 바꿀 수 있습니다.
ulimit -n 10000
이 명령은 Qdrant 서버를 실행하기 전에 실행해야 한다는 점, 꼭 기억해 두세요.
저장 공간 부족 (HTTP 507)
v1.19.0부터 사용 가능
노드에 리소스 쿼터가 설정되어 있으면, 쓰기를 받아줄 복제본을 가진 노드가 남아 있지 않을 수 있어요. 그 경우 클라이언트는 HTTP 507 Insufficient Storage 또는 gRPC ResourceExhausted 오류를 보게 됩니다.
Disk usage is at 95% of total capacity, exceeding the configured limit of 90%. Help: Reduce disk usage (e.g. delete points or drop collections), or raise `max_disk_usage_percent` in the global quota config.
관련 내용은 쿼터 초과 시점(When a Quota Is Exceeded) 문서를 함께 보면 좋아요.
이 오류를 해결하려면 자원을 확보하거나 한도를 올리면 됩니다.
- 더 이상 필요 없는 포인트를 삭제하거나 컬렉션을 내립니다. 포인트 삭제는 정확히 이런 이유로 쿼터 아래에서도 계속 허용돼요. 개별 벡터나 페이로드 키를 삭제하는 요청은 거부됩니다.
- 용량을 추가합니다. 용량 계획(Capacity Planning)을 참고하세요.
- 쿼터가 노드가 실제로 감당할 수 있는 수준보다 낮게 설정되어 있다면
PUT /quotas로 한도를 올립니다.
쓰기가 중단됐다가 사용량이 떨어지면 바로 재개되는 건 아니에요. 쿼터가 걸린 한도는 사용량이 해제 마진(release margin) 아래로 내려가야 풀리는데, 기본값은 한도 대비 5퍼센트포인트 아래입니다.
호환되지 않는 파일 시스템
Qdrant는 영구 파일 저장을 위해 몇 가지 요구 사항이 있어요. 가장 중요한 요구 사항은 파일 시스템이 반드시 POSIX 호환이어야 한다는 점입니다.
v1.15.0부터 Qdrant는 시작 시 파일 시스템 호환성을 런타임으로 검사해요. 알 수 없는 파일 시스템을 감지하면 다음과 같은 경고를 볼 수 있습니다.
WARN qdrant: There is a potential issue with the filesystem for storage path ./storage. Details: HFS/HFS+ filesystem support is untested
런타임 검사가 실패하면 오류 메시지를 보게 됩니다.
ERROR qdrant: Filesystem check failed for storage path ./storage. Details: FUSE filesystems may cause data corruption due to caching issues
이런 오류가 보고되면 현재 설정으로 계속 작업하는 것은 안전하지 않아요. 데이터를 잃을 위험이 있기 때문입니다.
호환되지 않는 파일 시스템으로 Qdrant를 계속 사용할 때 볼 수 있는 가장 흔한 오류는 다음과 같아요.
ERROR Panic occurred in file /qdrant/lib/gridstore/src/gridstore.rs at line 53: called `Result::unwrap()` on an `Err` value: OutputTooSmall { expected: 4, actual: 0 }
또는
ERROR Service internal error: task XXX panicked with message "called `Result::unwrap()` on an `Err` value: OutputTooSmall { expected: 4, actual: 0 }"
서비스 재시작 후 벡터 데이터가 사라지거나(전부 0으로 설정) 그럴 가능성도 있어요.
호환되지 않는 파일 시스템을 어떻게 피할까?
흔히 마주치는 호환되지 않는 파일 시스템 설정 중 하나는 Windows에서 WSL 기반 Docker 컨테이너를 사용하는 경우예요. Windows 폴더를 Qdrant Docker 컨테이너에 마운트하면, Windows 하이퍼바이저가 완전히 POSIX 호환이 아닌 공유 마운트를 만들어요.
바인드 마운트 대신 Docker 볼륨을 사용하는 편이 좋습니다.
# Create named volume docker volume create qdrant-storage # Use named volume with qdrant container docker run --rm -it \ -p 6333:6333 -p 6334:6334 \ -v qdrant-storage:/qdrant/storage qdrant/qdrant:v1.15.3
위처럼 하면 볼륨이 Linux 컨테이너 안에 유지되어 Windows와 공유되는 마운트에서 생기는 문제를 피할 수 있어요.
Collections 메타 WAL을 열 수 없음
분산 배포의 일부로 Qdrant 인스턴스를 시작할 때 이런 비슷한 오류 메시지를 만날 수 있어요.
Can ' t open Collections meta Wal: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }
이 메시지는 컬렉션을 로드할 수 없어 Qdrant가 시작되지 못한다는 뜻이에요. 관련된 WAL 파일을 현재 사용할 수 없는데, 보통 같은 파일을 다른 Qdrant 인스턴스가 이미 사용 중이기 때문입니다.
각 노드는 자신만의 별도 저장 디렉터리, 볼륨 또는 마운트를 가져야 해요.
형성된 클러스터가 각 노드와 데이터를 공유하고 올바른 위치에 배치해 주기 때문에 걱정할 필요는 없어요. Kubernetes를 쓰면 각 노드가 자신의 볼륨을, Docker를 쓰면 각 노드가 자신의 저장 마운트 또는 볼륨을, Qdrant를 직접 쓰면 각 노드가 자신의 저장 디렉터리를 가져야 합니다.
Python gRPC 클라이언트를 multiprocessing과 함께 사용할 때
Python gRPC 클라이언트를 multiprocessing과 함께 쓰면 이런 오류가 날 수 있어요.
<_InactiveRpcError of RPC that terminated with: status = StatusCode.UNAVAILABLE details = "sendmsg: Socket operation on non-socket (88)" debug_error_string = "UNKNOWN:Error received from peer {grpc_message:"sendmsg: Socket operation on non-socket (88)", grpc_status:14, created_time:"....."}"
이 오류는 multiprocessing이 같은 소켓을 공유하는 gRPC 채널의 복사본을 만들기 때문에 발생해요. 부모 프로세스가 채널을 닫으면 소켓도 닫히고, 자식 프로세스들이 닫힌 소켓을 사용하려 하기 때문입니다.
이 오류를 막으려면 multiprocessing의 시작 방법(start method)으로 forkserver 또는 spawn을 사용하면 돼요.
import multiprocessing multiprocessing . set_start_method ( "forkserver" ) # or "spawn"
또는 REST API, 비동기 클라이언트, 혹은 Python 클라이언트에 내장된 병렬화 기능(qdrant.upload_points(...) 같은 함수)을 사용하는 쪽으로 전환해도 됩니다.