ES /docs

error occurred while reprocess. capture_id: 681878, reason:Model has invalid state to reprocess, use

RCA: error occurred while reprocess. capture_id: 681878, reason:Model has invalid state to reprocess

Error Log#

Datadog Logs

text
error occurred while reprocess. capture_id: 681878, reason:Model has invalid state to reprocess, user_id: 5874

Impact#

  • Service: cupixworks-api
  • 발생 횟수: 3
  • 최초 발생: 2026-04-16T11:27:25.896Z
  • 최근 발생: 2026-04-16T11:30:52.319Z

Root Cause Summary#

사용자 yohan.kim@cupix.com (user_id: 5874)이 CLI를 통해 capture 681878, 681879, 681880에 대해 reprocess_capture 명령을 실행했으나, 해당 capture들이 이미 processing 중인 상태였기 때문에 reprocessible? 검증에서 실패했다. Capture 681878의 경우 첫 번째 reprocess 요청(11:26:16Z)이 성공하여 job 1018312가 생성되고 preprocessor agent가 실행된 상태에서, 약 1분 후(11:27:25Z) 두 번째 reprocess CLI 요청이 들어왔다. reprocessible? 메서드는 jobs.processing.exists?가 true이면 (즉, stopped 상태가 아닌 job이 존재하면) false를 반환하므로, 이미 실행 중인 job이 있는 capture에 대한 중복 reprocess 요청이 정상적으로 거부된 것이다. 이는 의도된 보호 로직이 정상 동작한 케이스이며, 실제 데이터 손실이나 기능 장애는 없다.

Technical Analysis#

Code Path#

  • Entry point: Cli::V1::CapturesController#reinvoke (app/controllers/cli/v1/captures_controller.rb:5)
ruby
# app/controllers/cli/v1/captures_controller.rb:5-18
def reinvoke
  capture_ids = params[:ids]
  command = params[:command]

  case command
  when 'reprocess_capture'
    results = CaptureOperation.reinvoke_captures(capture_ids, current_user)
  when 'reprocess_singleshot_capture'
    results = CaptureOperation.reinvoke_singleshot_captures(capture_ids, current_user)
  else
    raise Cupix::Errors::Parameter.new(code: 'ARG10001', reason: "Invalid command: #{command}")
  end

  render json: { results: results }
end
  • Orchestrator: CaptureOperation.reinvoke_captures (app/operations/capture_operation.rb:22-39)
ruby
# app/operations/capture_operation.rb:22-39
def reinvoke_captures(capture_ids, current_user)
  captures = ::Capture.where(id: capture_ids)
  results = []

  captures.each do |capture|
    Cupix::Logger.info("start reprocess captures. capture_id: #{capture.id}, user_id: #{current_user.id}")
    begin
      capture_invoker = CaptureInvoker.new(model: capture, current_user: current_user)
      capture_invoker.reprocess_capture
      results << { id: capture.id, status: 'success' }
    rescue StandardError => e
      Cupix::Logger.error("error occurred while reprocess. capture_id: #{capture.id}, reason:#{e.message}, user_id: #{current_user.id}", reprocess: { error: e })
      results << { id: capture.id, status: 'error', error: e.message }
    end
  end

  results
end
  • Validation point: CaptureInvoker#reprocess_capture (app/invokers/capture_invoker.rb:272-274)
ruby
# app/invokers/capture_invoker.rb:272-274
def reprocess_capture(opts = {})
  raise Cupix::Errors::PermissionDenied.new(code: 'PERM10000', reason: 'Permission denied') unless @model.reprocessible?
  raise Cupix::Errors::Entity.new(code: 'ENT10000', reason: 'Model has invalid state to reprocess') unless @model.reprocessible?
  • Failure point: ProcessibleCapture#reprocessible? (app/models/concerns/processible_capture.rb:67-72)
ruby
# app/models/concerns/processible_capture.rb:67-72
def reprocessible?
  return false if self.jobs.processing.exists?
  return false unless state_done?

  true
end
  • Job "processing" scope 정의: Statable::Job (app/models/concerns/statable/job.rb:13)
ruby
# app/models/concerns/statable/job.rb:13
scope :processing, -> { where.not(state: [:stopped]) }

jobs.processing scope는 statestopped가 아닌 모든 job을 "processing 중"으로 판단한다. 따라서 created, pending, starting, running, stopping 상태의 job이 하나라도 있으면 reprocessible?은 false를 반환한다.

기대 동작: capture에 아직 완료되지 않은 job이 있으면 reprocess를 거부해야 한다. 실제 동작: job 1018312가 running 또는 pending 상태에 있었으므로 jobs.processing.exists?가 true를 반환, reprocessible?이 false를 반환하여 ENT10000 에러가 raise되었다. 이는 의도된 동작이다.

Log Evidence#

사용한 Datadog 쿼리:

text
service:cupixworks-api "capture_id: 681878"
text
service:cupixworks-api status:error "reprocess"
text
service:cupixworks-api "CLI Request" "reinvoke" "captures" (681878 OR 681879 OR 681880)

타임라인 (capture 681878 기준, 모두 2026-04-16):

시각 (KST) 이벤트
20:26:16 start reprocess captures. capture_id: 681878, user_id: 5874 — 첫 번째 reprocess 시작 (성공)
20:26:42 Capture 681878 reset refinement job — reset 수행
20:26:42 Capture 681878 reset 3d_reconstruction — reset 수행
20:26:44 invoke capture processing for capture 681878. — processing 시작
20:26:44 Capture job is created for capture 681878. job_id: 1018312 — job 생성
20:26:44 preprocessor agent is invoked for capture 681878. job id: 1018312 — agent 실행
20:27:25 [CLI Request] POST reinvoke, ids:[681878], command:reprocess_capture — 두 번째 reprocess CLI 요청
20:27:25 start reprocess captures. capture_id: 681878, user_id: 5874 — reprocess 시도
20:27:25 error occurred while reprocess. capture_id: 681878, reason:Model has invalid state to reprocess — 실패
20:34:43 skatmaster is invoked for capture 681878. job id: 1018312 — 정상 processing 진행 중

나머지 2건도 동일 패턴:

text
20:30:51 — [CLI Request] reinvoke capture 681879 → error (job 1018313 실행 중)
20:30:52 — [CLI Request] reinvoke capture 681880 → error (job 1018315 실행 중)

모든 3건의 capture가 이후 정상적으로 skatmaster 처리를 진행한 것이 로그로 확인됨:

json
{
  "timestamp": "2026-04-16 20:34:43 KST",
  "message": "skatmaster is invoked for capture 681878. job id: 1018312",
  "class": "Capture",
  "function": "run_skat_master"
}
json
{
  "timestamp": "2026-04-16 20:37:17 KST",
  "message": "skatmaster is invoked for capture 681879. job id: 1018313",
  "class": "Capture",
  "function": "run_skat_master"
}
json
{
  "timestamp": "2026-04-16 20:39:28 KST",
  "message": "skatmaster is invoked for capture 681880. job id: 1018315",
  "class": "Capture",
  "function": "run_skat_master"
}

Fix Recommendation#

즉시 조치 (Critical)#

즉시 조치가 필요한 버그가 아님. reprocessible? 검증 로직이 정상 동작하여 이미 processing 중인 capture의 중복 reprocess를 올바르게 거부한 케이스이다.

단기 개선 (1주 이내)#

  • 에러 로그 레벨 변경: CaptureOperation.reinvoke_captures (app/operations/capture_operation.rb:33)에서 Cupix::Errors::Entity (ENT10000, "Model has invalid state to reprocess")를 catch할 때 Cupix::Logger.error 대신 Cupix::Logger.warn으로 로깅하는 것을 검토. 이는 사용자 오류(중복 요청)이지 시스템 장애가 아니므로, error 레벨 노이즈를 줄일 수 있다.
  • API 응답 개선: 현재 CaptureOperation은 rescue에서 에러를 catch하고 { status: 'error', error: e.message }로 응답한다. 에러 메시지에 "capture is currently processing, please try again later" 같은 사용자 친화적 메시지를 추가하면 CLI 사용자가 상황을 더 잘 이해할 수 있다.

장기 개선 (재발 방지)#

  • CLI/Admin UI에 reprocess 가능 여부 사전 확인: CLI 또는 Admin 인터페이스에서 reprocess 요청 전에 capture의 현재 상태와 활성 job 유무를 미리 표시하여, 사용자가 processing 중인 capture에 중복 요청을 보내지 않도록 UX를 개선할 수 있다.

Monitoring#

  • 현재 이 에러의 빈도가 높지 않으므로 (3건, 단일 사용자) 별도 알림은 불필요
  • 동일 에러가 다수 사용자에서 반복 발생시 모니터링 추가 검토:
text
service:cupixworks-api status:error "Model has invalid state to reprocess"

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial
  • 이 에러는 의도된 보호 로직의 정상 동작이며, capture processing에 실제 영향 없음. 3건 모두 동일 사용자(user_id: 5874)의 중복 CLI 요청으로 발생. 로그 레벨을 warn으로 변경하면 error 노이즈를 줄일 수 있다.