OpenClaw 크래시 연쇄 사례 분석: 모두 하나의 근본 원인을 공유합니다
요약
에이전트 시스템의 프로덕션 환경에서 발생하는 크래시 사례를 분석하여 '상태 증명 함정(Proof-of-State Trap)'이라는 근본 원인을 제시합니다. 재시작 시 무효화되는 식별자에 의존할 때 발생하는 세션 만료, PID 잠금 오작동, 상태 불일치 등의 문제를 다룹니다.
핵심 포인트
- 재시작 후 무효화되는 식별자에 의존하는 '상태 증명 함정' 주의
- 세션 핸들 교체 시 클라이언트와 서버 간 생명주기 일치 필요
- 컨테이너 재사용 시 PID 기반 잠금 확인 방식의 위험성
- 재시작 전 상태가 현재의 생존 여부로 오인되지 않도록 설계
저는 ARK (Agent Reliability Kit)의 제작자인 观一 (Guan-Yi)입니다. 지난 몇 주 동안 저는 프로덕션 환경에서 발생하는 에이전트 크래시(agent crashes)에 대한 사후 분석(autopsies)을 진행해 왔습니다. 이는 모델의 환각(hallucination) 문제가 아니라, 재시작 후 인프라가 스스로에게 거짓말을 하는 아주 단순한 문제였습니다. 처음에는 서로 관련이 없어 보였지만, 사실 그렇지 않았습니다.
이들은 하나의 근본 원인을 공유합니다. 저는 이를 **상태 증명 함정 (Proof-of-State Trap)**이라고 부릅니다:
"X가 여전히 살아있는가 / 여전히 당신의 것인가 / 여전히 현재 인스턴스인가"에 대한 모든 판단이, 재시작 후에 무효화되는 식별자(identifier)에 의존한다면, 이는 소리 없이 영구적인 거부(veto)로 변질됩니다.
저를 확신하게 만든 네 가지 사례는 다음과 같습니다.
사례 1 — 세션 핸들(Session handle)이 만료되었으나 새 핸들이 반환되지 않음 (#113434)
상위 generation이 만료되었습니다. 서버는 이미 새로운 핸들로 교체(rotated)되었지만, 클라이언트는 여전히 이전 핸들을 보유하고 있었습니다. 증상: 의문의 400 에러 / "세션 무효(session invalid)". 근본 원인: 재시작 시 상태 생명주기(state lifecycle)가 일치하지 않았습니다. 이 진단은 이후 병합된 상위 PR(#114056 / #114401 / #114478)을 통해 독립적으로 확인되었습니다.
사례 2 — 컨테이너 재사용으로 인한 PID 잠금(lock) 오작동 (#114234)
"잠금이 유지되고 있는가?"를 확인하는 체크 과정에서 PID 생존 여부(liveness)를 사용했습니다. 컨테이너 재빌드 후 PID가 재사용되면서, 잠금이 "영구적으로 살아있는" 것처럼 보였고 캐시가 얼어붙었습니다(froze). 근본 원인: 잠금 유효성의 증거가 재시작 시 만료되는 식별자였습니다.
사례 3 — 게이트웨이(Gateway) 재시작 후 세션이 running 상태로 남음 (#114255)
게이트웨이 재시작 후, 세션의 상태 문자열이 running 상태에 멈춰 있었습니다. 이로 인해 하위 코드(downstream code)는 "여전히 진행 중"이라고 결론짓고 영원히 차단(blocked)되었습니다. 근본 원인: 재시작 전의 상태가 현재의 생존 여부(liveness)로 취급되었습니다.
사례 4 — LaunchAgent의 일회성 업데이트가 영구적인 재시작 루프가 됨 (#115326)
이 사례는 해당 패턴을 부정할 수 없게 만든 결정적인 사건이었습니다. 한 커뮤니티 개발자(robingutsche)는 "자정에 크래시가 발생하고, 재시작하면 해결되지만, 다시 크래시가 발생하는" 루프의 원인을 추적하여, keepalive가 설정된 launchctl submit -l com.openclaw.beta-update-once 작업임을 밝혀냈습니다. 즉, 일회성 업데이트가 EACCES 오류로 실패했을 때, launchd가 이를 영구적으로 재시작하면서 관리되는 게이트웨이를 반복적으로 종료시키고 차단기(breaker)를 작동시킨 것입니다. 그는 또한 차단기가 절대 자동으로 해제되지 않으며, 채널이 실제로는 not-running 상태임에도 status --all 명령어가 OK를 보고한다는 사실도 발견했습니다.
그는 이를 유지 관리자 수준의 재현 보고서로 작성했습니다. 저는 이를 세 가지 독립적인 버그로 정리하여 ARK의 회고(retrospective)의 핵심 내용으로 아카이브했습니다.
불변의 법칙 (The invariant)
네 가지 사례 모두 하나의 실행 가능한 규칙으로 귀결됩니다:
상태 증명(Proof-of-state)은 반드시 특정 인카네이션(incarnation, 실행 인스턴스)에 결합되어야 합니다. 재시작에 취약한 식별자 — PID, 오래된 핸들(stale handle), 재시작 전의 상태 문자열, 오래된 차단기 래치(breaker latch) — 에 의존하는 모든 "X가 여전히 살아 있음 / 여전히 당신의 소유임 / 여전히 현재 인스턴스임" 식의 체크는 시한폭탄입니다.
이것이 제가 ARK를 구축한 이유이기도 합니다. "이 상태 주장(state claim)이 현재 인스턴스와 일치하는가?"를 새벽 3시에 뒤늦게 발견하는 것이 아니라, 자동으로 체크 가능한 상태 항목(health item)으로 만들기 위함입니다.
가장 치명적인 지점
운영 환경의 에이전트 크래시는 모델의 문제가 아니라 99% 엔지니어링 단언(assertion) 실패입니다. 패턴은 다음과 같습니다: "PID가 살아 있음 ≠ 잠금(lock)이 유효함; 세션 상태가 존재함 ≠ 프로세스가 살아 있음; 설정이 유효함 ≠ 런타임이 건강함." "X가 여전히 유효함"이라는 모든 단언은, 현재 인스턴스에 결합되지 않는 한 재시작 이후에는 거짓이 됩니다.
만약 귀하의 에이전트가 밤중에 크래시가 발생하고, 재시작된 후 다시 크래시가 발생한다면 — 그것은 일련의 결함(family defect)이 문을 두드리고 있는 것입니다. 무료 진단 스레드에 로그를 남겨주세요. 자동 생성된 가짜 보고서가 아닌, 제가 직접 읽겠습니다.
전체 기술 보고서 (지속 업데이트 중): https://ark-6ek.pages.dev/proof-of-state-trap
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기