ES /docs

Index error - [400] {"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"failed to p

RCA: Elasticsearch geo_point mapper_parsing_exception in ElementTrace indexing

Overview#

What Happened#

2026-05-22 04:0004:43 UTC 사이에 cupixworks-api 서비스에서 ElementTrace를 Elasticsearch에 인덱싱하는 과정에서 mapper_parsing_exception 에러가 6,356회 발생했다. BIM 좌표계의 값을 geo_point의 latitude/longitude로 직접 사용하면서, 유효 범위(-9090)를 벗어나는 값(예: 2139310, -167596)이 Elasticsearch에 전달되어 거부되었다.

Quick Facts#

Field Value
exception.class Elasticsearch::Transport::Transport::Errors::BadRequest
exception.message mapper_parsing_exception: failed to parse field [location] of type [geo_point]
top_frame app/models/concerns/searchable.rb:51 (Index error), app/models/concerns/searchable.rb:116 (ElasticsearchError)
env production, us-west-2

Timeline#

  1. 2026-05-22T04:00:01Z — 최초 에러 발생 (ElementTrace._index_document)
  2. 2026-05-22T04:43:07Z — 마지막 에러 기록
  3. 2026-05-22T05:00:00Z — Error Sweeper 수집

Error Log#

Datadog Logs

text
Index error - [400] {"error":{"root_cause":[{"type":"mapper_parsing_exception","reason":"failed to parse field [location] of type [geo_point]"}],"type":"mapper_parsing_exception","reason":"failed to parse field [location] of type [geo_point]","caused_by":{"type":"illegal_argument_exception","reason":"illegal latitude value [2139310.163528784] for location"}},"status":400}

Impact#

  • Service: cupixworks-api
  • 발생 횟수: 6,356
  • 최초 발생: 2026-05-22T04:00:01.281Z
  • 최근 발생: 2026-05-22T04:43:07.973Z

ElementTrace 인덱싱 실패로 인해 해당 element trace들의 Elasticsearch 문서가 생성/갱신되지 않았다. 이는 SQA Editing의 Geo Aggregation 기반 작업 분할(TSLA-10800)에서 해당 element trace들이 누락되어, 작업 바구니(Editing) 할당이 불완전해질 수 있다.

Root Cause Summary#

Properties::Element#bim_center_location 메서드가 BIM 모델의 로컬 좌표(bim_bounds + offset + origin)를 계산하여 { lat: center_y, lon: center_x } 형태로 반환하는데, 이 값에 대한 geo_point 유효 범위 검증이 전혀 없다. BIM 좌표는 밀리미터 또는 미터 단위의 로컬 좌표계(State Plane, UTM 등)를 사용하므로, offset/origin이 큰 모델에서는 수십만수백만 단위의 값이 생성된다. Elasticsearch의 geo_point는 latitude -9090, longitude -180~180만 허용하므로 400 에러로 거부된다.

Technical Analysis#

Code Path#

  1. Entry point: ElementTrace가 create/update 되면 after_commit 콜백에서 _index_document 또는 _update_document가 호출된다.
app/models/concerns/searchable.rb:12-18ruby
after_commit on: [:create] do
  _index_document
end

after_commit on: [:update] do
  _update_document
end
  1. Serialization: as_indexed_json에서 ElementTraceSerializer를 사용하여 인덱싱할 JSON을 생성한다.
app/serializers/element_trace_serializer.rb:68-70ruby
attribute :location do |element_trace|
  element_trace.element&.bim_center_location
end
  1. Failure point: bim_center_location이 BIM 좌표를 그대로 geo_point 형식으로 반환한다. 범위 검증 없음.
app/models/concerns/properties/element.rb:104-121ruby
def bim_center_location
  return nil if bim_bounds.blank?
  return nil unless bim_bounds.is_a?(Array) && bim_bounds.size == 6

  x_min, y_min, _z_min, x_max, y_max, _z_max = bim_bounds
  center_x = (x_min + x_max) / 2.0
  center_y = (y_min + y_max) / 2.0

  bim = bim_revision&.bim
  if bim.present?
    offset = bim.offset || [0, 0, 0]
    origin = bim.origin || [0, 0, 0]
    center_x += (offset[0] || 0) + (origin[0] || 0)
    center_y += (offset[1] || 0) + (origin[1] || 0)
  end

  { lat: center_y, lon: center_x }
end
  1. Error handling: 인덱싱 실패 시 BulkIndexWorker로 재시도를 enqueue한다. 같은 데이터로 재시도하므로 동일 에러가 반복된다.
app/models/concerns/searchable.rb:50-53ruby
rescue StandardError => e
  Cupix::Logger.error("Index error - #{e.message}", class: self.class.name, function: __method__)
  BulkIndexWorker.perform_async(self.class.name, [id], 'index')
end
  1. Retry amplification: BulkIndexWorkerretry: 5로 설정되어 있어, 한 번 실패한 인덱싱이 최대 5회 추가 재시도된다. 하지만 데이터 자체가 잘못되어 있으므로 모든 재시도가 실패한다.
app/workers/bulk_index_worker.rb:3ruby
sidekiq_options queue: :default, retry: 5

Log Evidence#

Datadog 검색 쿼리:

text
service:cupixworks-api status:error "mapper_parsing_exception" "illegal latitude"

로그에서 확인된 비정상 latitude 값 패턴 (모두 동일 BIM 모델의 element들로 추정):

json
{"reason": "illegal latitude value [-167596.0191495257] for location"}
{"reason": "illegal latitude value [-167597.266924526] for location"}
{"reason": "illegal latitude value [-167593.9331745257] for location"}
{"reason": "illegal latitude value [-167595.5047995257] for location"}
{"reason": "illegal latitude value [-167595.8095995257] for location"}

클러스터 대표 에러의 latitude 값:

json
{"reason": "illegal latitude value [2139310.163528784] for location"}

에러 발생 함수:

  • _index_document — 새 document 생성 시
  • _update_document — 기존 document 갱신 시

class 태그: ElementTrace (모든 에러가 동일 모델)

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 BIM 좌표가 범위 검증 없이 geo_point로 직접 사용됨 bim_center_location 코드에 범위 체크 없음 (element.rb:104-121). 로그의 latitude 값이 -167596, +2139310으로 BIM 로컬 좌표계 범위. TSLA-10800 문서에서 "BIM bounds를 geo_point로 변환" 설계 확인 Confirmed
H2 Elasticsearch 매핑이 잘못 설정되어 coerce: true 없이 strict 모드로 동작 ES는 기본적으로 geo_point에 coerce 미적용. 매핑에 coerce: true 없음 (searchable/element_trace.rb:114) coerce를 켜도 -9090 범위를 넘는 값은 변환 불가 (coerce는 -180180 longitude wrap만 처리). 근본 원인은 데이터 자체가 잘못됨 Rejected
H3 특정 BIM 모델의 offset/origin 데이터가 손상됨 로그에서 -167596 근처 값이 반복됨 (동일 BIM 모델의 여러 element) 설계 문서에서 BIM 좌표를 geo_point로 사용하는 것이 의도된 동작. 좌표가 크다는 것은 대형 건물이나 실좌표 기반 BIM에서 정상적 시나리오 Rejected

Fix Recommendation#

즉시 조치 (Critical)#

app/models/concerns/properties/element.rb:104-121bim_center_location 메서드에서 반환 전 geo_point 유효 범위를 검증하여, 범위를 벗어나면 nil을 반환하도록 한다.

  • 수정 위치: app/models/concerns/properties/element.rb line 120 (return 직전)
  • latitude가 -9090, longitude가 -180180 범위를 벗어나면 nil 반환
  • nil 반환 시 ES에 location 필드가 저장되지 않으므로 에러가 사라진다

단기 개선 (1주 이내)#

TSLA-10800의 원래 설계 의도를 재검토해야 한다. BIM 로컬 좌표를 geo_point로 사용하는 것은 Geo Aggregation을 위한 편의 구현이었으나, 실좌표 기반 BIM 모델에서는 동작하지 않는다. 두 가지 방향 중 택일:

  1. 좌표 정규화: BIM 좌표를 -9090 / -180180 범위로 정규화(normalize)하여 매핑. geohash aggregation의 목적은 "근접 element끼리 그룹핑"이므로, 상대적 위치 관계만 유지되면 된다.
  2. 별도 필드 사용: geo_point 대신 float 타입의 bim_x, bim_y 필드를 사용하고, range query + script 기반 그룹핑으로 전환.

장기 개선 (재발 방지)#

  • Searchable concern의 _index_document rescue 블록에서 BulkIndexWorker로 무조건 재시도하는 패턴을 개선. 400 에러(클라이언트 잘못)는 재시도 불필요 — 5xx 에러만 재시도하도록 분기.
  • ES 인덱싱 serializer에서 geo_point 필드에 대한 공통 validation concern 추가.

Monitoring#

추가할 알림:

text
service:cupixworks-api status:error "mapper_parsing_exception"

geo_point 관련 인덱싱 실패를 즉시 감지하기 위한 Datadog monitor를 설정한다. threshold: 10회/5분 이상 시 alert.

Risk Assessment#

  • Risk level: medium
  • 예상 복잡도: standard

데이터 무결성 영향: 해당 element trace들이 ES에 인덱싱되지 않아 Geo Aggregation 기반 Editing 분할에서 누락될 수 있다. 다만 SQA 작업 흐름의 보조 기능(자동 그룹핑)이므로 서비스 전체 가용성에는 영향 없음.