ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'spacetimes.summary_text' in 'field list'
RCA: ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'spacetimes.summary_text' in 'field list'
Overview#
What Happened#
2026-08-06 14:27 KST경 cupixvista-api (tesla vista 배포)에서 Api::V1::FacilitiesController#update_spacetime 요청이 spacetimes 테이블에 summary_text 컬럼을 쓰려다 Mysql2::Error: Unknown column 'spacetimes.summary_text' in 'field list' 로 실패했다. 원인은 blue/green 배포 순간의 transient 문제가 아니라, 특정 환경의 DB 에서 spacetimes.summary_text 컬럼이 아예 생성되지 않은 migration version-ordering schema drift 다. 현재 배포된 코드(facility_repository.rb:132)는 항상 이 컬럼을 write 하므로, drift 된 DB 에서는 capture-intelligence-agent 가 생성한 spacetime summary 저장이 결정론적으로 실패한다. 이 결함을 정확히 진단·수정하는 커밋(707aac515 TSLA-13490)은 이미 존재하지만 develop/master 에 미병합이며 배포판 c1c2bbd4 에 포함되어 있지 않다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | ActiveRecord::StatementInvalid (rescue 후 Cupix::Errors::Parameter) |
| exception.message | Mysql2::Error: Unknown column 'spacetimes.summary_text' in 'field list' |
| top_frame | vendor/bundle/ruby/3.3.0/gems/mysql2-0.5.4/lib/mysql2/client.rb (_query) |
| runtime | Ruby 3.3.0, Rails (ActiveRecord 7.2), mysql2 0.5.4 |
| deploy | production-us-west-2-20260804t0618z0-c1c2bbd4-cupixvista ~ ...20260804t1219z0-c1c2bbd4 (동일 SHA c1c2bbd4) |
| env | production, us-west-2 |
| is_crash | false (HTTP 400 로 매핑) |
Affected Teams#
cupixvista-api 는 로그 0건이나, 동일 tesla 코드의 cupixworks-api 배포에서 같은 메시지·코드·엔드포인트로 28건 관측되어 영향 범위를 대변한다. 모든 요청은 UA cupix-capture-intelligence-agent 이며 여러 tenant 에 걸쳐 있다 — broad, 결정론적 drift 임을 뒷받침한다.
| Team / Domain | Error Count (14d, cupixworks-api) | Impact |
|---|---|---|
| bnbuilders | 13 | spacetime summary 저장 실패 (동일 spacetime 927107 반복 재시도) |
| walmart | 9 | spacetime summary 저장 실패 |
| pclconstruction | 2 | spacetime summary 저장 실패 |
| southlandind | 2 | spacetime summary 저장 실패 |
| whitingturner | 1 | spacetime summary 저장 실패 |
| clark-vdc | 1 | spacetime summary 저장 실패 |
Timeline#
- 2026-03-10 07:55 KST — 원본 migration
20260306071939_add_summary_to_spacetimes커밋(TSLA-12069). version 은20260306071939로 backdated. - 2026-07-06 13:31 KST — schema drift 를 진단·수정하는 커밋
707aac515(TSLA-13490) 작성. 브랜치origin/jarvis/TSLA-13490에만 존재, 미병합. - 2026-08-06 14:06 KST —
cupixworks-api에서update_spacetime400 발생 관측 시작 (14d retention 창 첫 로그). - 2026-08-06 14:27 KST —
cupixvista-apiET issuefirst_seen. - 2026-08-06 14:32 KST —
cupixvista-apiET issuelast_seen(occurrence 16). cupixworks-api 에서는 14:42 KST 이후로도 계속 발생.
Error Log#
Mysql2::Error: Unknown column 'spacetimes.summary_text' in 'field list'
Impact#
- Service:
cupixvista-api(tesla vista 배포; 동일 tesla 코드의cupixworks-api에서도 동일 발생) - 발생 횟수: 16 (ET issue, cupixvista-api)
- 최초 발생: 2026-08-06 14:27 KST
- 최근 발생: 2026-08-06 14:32 KST
Root Cause Summary#
spacetimes.summary_text 컬럼을 추가하는 migration 20260306071939_add_summary_to_spacetimes 는 실제로는 2026-03-09 에 커밋되었으나 version timestamp 가 20260306071939 로 backdated 되었다. Rails 는 schema_migrations 의 max version 보다 큰 version 만 실행하므로, 이 migration 이 병합되기 전에 이미 더 높은 version(20260309000001_add_summary_state_columns 등)을 적용한 환경은 backdated migration 을 영영 건너뛴다. 그 결과 db/schema.rb (regenerate 시 컬럼 포함, schema.rb:4126 t.text "summary_text")와 달리 해당 DB 에는 spacetimes.summary_text 컬럼이 존재하지 않는다. 현재 배포 코드 FacilityRepository#update_spacetime 는 summary 저장 시 항상 spacetime.summary_text = spacetime.summary_text_for_search 를 세팅하고 save! 하므로(facility_repository.rb:132,143), drift 된 DB 에서 UPDATE 가 Unknown column 'spacetimes.summary_text' 로 실패한다. 이는 배포 cutover transient 가 아니라 결정론적 schema drift 버그이며, 이미 정확히 진단·수정하는 커밋(707aac515 TSLA-13490, forward-dated idempotent re-add migration)이 있으나 develop/master 에 미병합·미배포 상태다.
Technical Analysis#
Code Path#
- Entry point:
PUT /api/v1/facilities/:key/spacetimes/:spacetime_id→Api::V1::FacilitiesController#update_spacetime(routeconfig/routes.rb:1342) - Repository:
FacilityRepository#update_spacetime(app/repositories/facility_repository.rb:122) - Failure point:
spacetime.save!(facility_repository.rb:143) —summary_text컬럼 write 시 MySQL 이 컬럼 부재로 거부 - 매핑: rescue →
Cupix::Errors::Parameter ARG10001(facility_repository.rb:145) →client_400_error→ HTTP 400 (app/controllers/concerns/client_error_controller.rb:10,61)
update_spacetime 는 summary 파라미터가 있으면 summary_text 컬럼에 flat 검색 텍스트를 미리 저장한다:
def update_spacetime(spacetime_id, params)
raise Cupix::Errors::PermissionDenied.new(code: 'PERM10000', reason: 'Permission denied') unless self.model.updatable_by?(self.current_user)
spacetime = @model.spacetimes.find_by(id: spacetime_id)
raise Cupix::Errors::NotFound.new(code: 'ARG10002', reason: 'Spacetime not found') if spacetime.nil?
if params[:summary].present?
summary = params[:summary].is_a?(ActionController::Parameters) ? params[:summary].permit!.to_h : params[:summary]
spacetime.validate_summary!(summary)
spacetime.summary = summary
spacetime.summary_text = spacetime.summary_text_for_search # summary_text 컬럼 write
end
spacetime.summary_state = params[:summary_state] if params.key?(:summary_state)
if params.key?(:summary_vector_embedding)
spacetime.validate_summary_vector_embedding!(params[:summary_vector_embedding])
spacetime.summary_vector_embedding = params[:summary_vector_embedding]
end
begin
spacetime.save! # 여기서 Unknown column 'spacetimes.summary_text' 발생
rescue StandardError => e
raise Cupix::Errors::Parameter.new(code: 'ARG10001', reason: 'Invalid argument', message: e.message)
end
spacetime
end
현재 스키마에는 컬럼이 존재한다 — 즉 코드가 잘못된 컬럼을 참조하는 것이 아니라, 특정 DB 만 컬럼이 누락된 drift 다:
t.json "summary"
t.string "summary_state", default: "none", null: false
t.text "summary_text"
t.json "summary_vector_embedding"
원본 migration 은 backdated version 을 가진다:
class AddSummaryToSpacetimes < ActiveRecord::Migration[7.2]
def change
change_table :spacetimes, bulk: true do |t|
t.json :summary
t.text :summary_text
end
end
end
기대 동작: summary 파라미터 저장 시 summary_text 컬럼에 flat text 를 write 하고 200 반환.
실제 동작: drift 된 DB 에서 summary_text 컬럼이 없어 save! 가 Mysql2::Error: Unknown column 으로 실패 → rescue StandardError 가 이를 ARG10001 400 으로 매핑 → agent 의 summary 저장이 조용히 소실.
Log Evidence#
Datadog 쿼리 (cupixvista-api 는 retention 창 내 로그 0건, 동일 코드의 cupixworks-api 로 실증):
service:cupixvista-api "summary_text"
(service:cupixvista-api OR service:cupixworks-api) "spacetimes.summary_text"
cupixworks-api 에서 28건 관측. 대표 로그 항목(원문):
{
"timestamp": "2026-08-06T05:06:14.171Z",
"service": "cupixworks-api",
"status": "info",
"message": "[400] PUT /api/v1/facilities/rk93lz/spacetimes/1525775 (Api::V1::FacilitiesController#update_spacetime)",
"attributes": {
"error": {
"reason": "Invalid argument",
"code": "ARG10001",
"message": "Mysql2::Error: Unknown column 'spacetimes.summary_text' in 'field list'",
"class": "Cupix::Errors::Parameter"
},
"action": "update_spacetime",
"controller": "Api::V1::FacilitiesController",
"tenant": "cupix",
"user_agent": "cupix-capture-intelligence-agent",
"team": { "domain": "whitingturner", "id": 140 },
"params": { "fields": ["id","summary","summary_state","facility","record","level"], "key": "rk93lz" }
},
"tags": ["version:production-us-west-2-20260805t2305z0-c1c2bbd4-cupixworks"]
}
분포 (14d, cupixworks-api, 위 쿼리 28건):
- 100%
action: update_spacetime, 100%ARG10001/ HTTP 400 - UA 전부
cupix-capture-intelligence-agent - 발생 시각 05:06~05:42+ UTC 로 지속 (transient burst 아님), 여러 tenant(bnbuilders 13, walmart 9, pclconstruction 2, southlandind 2, whitingturner 1, clark-vdc 1)
- deploy version 3종 전부 동일 SHA
c1c2bbd4(20260805t2305z0,20260806t0214z0,20260806t0341z0) → old/new 코드 mismatch 아님 - 동일 spacetime
927107(team bnbuilders) 8회 이상 반복 → agent 결정론적 재시도
TSLA-13490 커밋 메시지가 이 정확한 메커니즘을 진단한다:
Diagnosis: the column IS defined by 20260306071939_add_summary_to_spacetimes
and IS present in db/schema.rb (spacetimes block, line ~4150) ... The original
migration was committed 2026-03-09 but backdated to a 2026-03-06 version.
Environments that had already applied a higher-version migration (e.g.
20260309000001) before this one merged skipped it, because Rails only runs
migrations with a version greater than max(schema_migrations).
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | Migration version-ordering schema drift — backdated migration 20260306071939 이 higher-version 을 이미 적용한 DB 에서 skip 되어 summary_text 컬럼 부재 |
schema.rb:4126 컬럼 존재하나 코드가 write; 커밋 707aac515(TSLA-13490) 이 동일 메시지·원인 진단; 원본 migration 커밋일 2026-03-09 vs version 20260306071939 backdated; higher-version 20260309000001 존재 |
— | Confirmed |
| H2 | blue/green 배포 cutover 시점의 transient schema/code mismatch (ispring acdd2caa 유형) |
05:2x UTC 창 발생, is_crash:false |
로그가 05:06~05:42+ 지속 발생·다수 tenant·동일 SHA c1c2bbd4 3개 deploy 판 전부에서 재발 → old/new mismatch 아니라 결정론적. regression 필드 부재 | Rejected |
| H3 | 코드가 존재하지 않는 컬럼을 잘못 참조 (a59d1eba records.name 유형) |
메시지 형태 동일 | schema.rb:4126 에 컬럼 정의 존재, migration 도 정의 → 코드-스키마는 정합, 특정 DB 만 drift |
Rejected |
| H4 | client 입력 오류 (noise) | HTTP 400 / ARG10001 로 매핑됨 | 입력 무관 — 서버측 컬럼 부재가 원인. rescue 가 schema 오류를 400 으로 mis-map 한 것일 뿐 | Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
- 이미 작성된 수정 커밋
707aac515(TSLA-13490, 브랜치origin/jarvis/TSLA-13490)의 open PR 을 develop/master 로 병합·배포한다. 이 커밋은 forward-dated idempotent migration20260613000000_readd_summary_columns_to_spacetimes를 추가하여 drift 된 DB 에서만summary/summary_text컬럼을 조건부 재생성하고, 이미 있는 환경에서는 no-op 이다 (column_exists?가드 사용). 본 클러스터는 신규 코드 작업이 아니라 미병합 PR 병합으로 해소되는 duplicate 성격이다.
class ReaddSummaryColumnsToSpacetimes < ActiveRecord::Migration[7.2]
def change
change_table :spacetimes, bulk: true do |t|
t.json :summary unless column_exists?(:spacetimes, :summary)
t.text :summary_text unless column_exists?(:spacetimes, :summary_text)
end
end
end
단기 개선 (1주 이내)#
update_spacetime의rescue StandardError => e → ARG10001(400)(facility_repository.rb:144-145)이 schema 오류·DB 오류 등 server-side 결함을 client 400 으로 뭉뚱그려 오분류한다.ActiveRecord::StatementInvalid같은 서버측 예외는 5xx 로 표면화하도록 rescue 를 좁혀, 이런 drift 가 400 뒤에 숨어 조용히 데이터 소실되는 것을 방지한다 (프런트/agent 응답 계약 조율 필요).
장기 개선 (재발 방지)#
- migration version backdating 금지 규칙 + CI 검증:
db/schema.rb에 존재하는 컬럼이 실제 target 환경 DB 에 모두 반영되는지 배포 파이프라인에서schema_migrations정합성(drift) 검사. - 컬럼 추가 migration 은 version 이 반드시 병합 시점 기준 최신이 되도록 강제(pre-merge lint), 또는 idempotent
column_exists?가드 패턴을 컬럼 추가 migration 표준으로 채택.
Monitoring#
배포 후 재발 여부 확인 (release dashboard timeseries widget 용):
service:cupixvista-api "Unknown column 'spacetimes.summary_text'"
(service:cupixvista-api OR service:cupixworks-api) "spacetimes.summary_text" @action:update_spacetime
(service:cupixvista-api OR service:cupixworks-api) @action:update_spacetime @error.code:ARG10001
Risk Assessment#
- Risk level: medium (사용자 500 은 아니나 agent 의 spacetime summary 저장이 조용히 소실 → capture intelligence 검색/요약 데이터 결손)
- 예상 복잡도: trivial (idempotent migration 병합·배포; 코드 로직 변경 없음)
Noise Verdict#
bug — spacetimes.summary_text 컬럼이 backdated migration 누락으로 특정 DB 에 아예 없어 agent 의 summary 저장이 결정론적으로 실패하는 진짜 schema drift 결함이며, 이미 진단·수정된 미병합 PR(TSLA-13490)을 배포하면 해소된다.