StandardError - wrong number of arguments (given 1, expected 0)
RCA: StandardError - wrong number of arguments (given 1, expected 0)
Overview#
What Happened#
Facility Transfer 작업 중 Progress 레코드를 Elasticsearch에 재색인하는 단계에서 ProgressSerializer가 ArgumentError: wrong number of arguments (given 1, expected 0)를 던졌다. cupixworks-worker (Sidekiq) 환경에서 2026-06-06 ~ 2026-06-08 사이 총 20건이 발생했고, 모두 BulkIndexWorker로 재시도된 뒤 Sidekiq job died after all retries 상태로 종료되었다. 직접적 원인은 progress_serializer.rb:91의 attribute :record_completed_at, &:record_complete_at 작성 패턴이 Symbol#to_proc의 arity 동작 때문에 fast_jsonapi가 메서드를 1-인자(serialization_params)로 호출하게 만들기 때문이다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | StandardError (실제 원인은 ArgumentError) |
| exception.message | wrong number of arguments (given 1, expected 0) |
| top_frame | app/models/concerns/properties/progress.rb:91:in 'record_complete_at' |
| serializer | app/serializers/progress_serializer.rb:91 |
| runtime | Ruby 3.3 / Rails (tesla repo) |
| deploy | production-us-west-2-20260605T0515Z0-8562b202-cupixworks |
| env | production / us-west-2 |
| trigger | Facility Transfer ([Transfer][854] ... fqgvj ...) → Progress re-index |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
| cupixworks-worker (Progress indexing / Facility Transfer) | 20 | Transfer 대상 facility의 Progress 레코드가 Elasticsearch에 갱신되지 않아 검색·통계 결과가 stale 상태가 됨. Sidekiq job들이 retry 후 dead 큐로 이동. |
Timeline#
- 2026-06-06 20:13 KST — 첫 발생 (
first_seen).[Transfer][854]Facility Transfer 작업 도중 Progress_update_document실패. - 2026-06-06 20:13 ~ 21:00 KST — 첫 번째 burst (Transfer 854 진행 중, 12건).
- 2026-06-07 21:57 KST — 두 번째 발생 묶음 (2건).
- 2026-06-08 10:22 ~ 10:26 KST — 세 번째 burst, 마지막 발생(
last_seen)에서Sidekiq job died after all retries기록.
Error Log#
StandardError - wrong number of arguments (given 1, expected 0)
Impact#
- Service:
cupixworks-worker - 발생 횟수: 20
- 최초 발생: 2026-06-06 20:13 KST
- 최근 발생: 2026-06-08 10:26 KST
- 영향: Facility Transfer 도중 Progress 레코드 인덱싱 실패.
_update_document1차 실패 후BulkIndexWorker.perform_async(..., 'index')로 재시도되지만 동일한 직렬화 경로를 거치므로 retry 도 모두 실패하여Sidekiq job died after all retries로 종결. Elasticsearch 인덱스의 Progress 도큐먼트가 transfer 이후 최신 상태로 동기화되지 않아 검색·필터·집계 결과에 stale 데이터가 노출될 수 있음.
Root Cause Summary#
ProgressSerializer에서 attribute :record_completed_at, &:record_complete_at로 작성한 부분이 원인이다. Ruby에서 &:method_name은 Symbol#to_proc을 호출하여 Proc을 만들고, 이 Proc의 arity는 Ruby 2.7+ 에서 -2이다 (->(receiver, *args) { receiver.method_name(*args) }). fast_jsonapi 1.5의 Attribute#serialize는 method.arity.abs == 1 ? method.call(record) : method.call(record, serialization_params) 분기로 호출 인자 수를 결정하는데, (-2).abs == 2 != 1이므로 항상 2-인자 분기를 타고 record.record_complete_at(serialization_params)로 호출된다. 그러나 Properties::Progress#record_complete_at은 0-인자 메서드이므로 ArgumentError: wrong number of arguments (given 1, expected 0)이 발생한다. 이 코드는 2023-04-11 (commit 1f816867, TSLA-5369)부터 존재했으며, 평소에는 as_indexed_json이 호출되지 않거나 호출되더라도 다른 직렬화 경로를 타서 발생하지 않았으나, [Transfer][854] Facility Transfer 작업이 모든 Progress 레코드의 _update_document → as_indexed_json 경로를 강제하면서 수면 위로 드러났다.
Technical Analysis#
Code Path#
- Entry point: Facility Transfer 워커 →
Progress#_update_document searchable.rb:55_update_document→ 변경된 컬럼이cached/sys에 포함되면as_indexed_json호출searchable/progress.rb:232as_indexed_json→ProgressSerializer.new(self, {...})생성progress_serializer.rb:91직렬화 시도fast_jsonapi/attribute.rb:14Proc 호출 분기 → 2-인자 호출- Failure point:
progress.rb:91record_complete_at(0-인자 메서드 호출에 1 인자 전달) searchable.rb:118rescue StandardError => e→Cupix::Logger.error("StandardError - #{e.message}", ...)→BulkIndexWorker.perform_async(self.class.name, [id], 'index')- 재시도(
BulkIndexWorker)도 동일한 직렬화 경로를 타기 때문에 모두 실패 →Sidekiq job died after all retries
attribute :record_completed_at, &:record_complete_at
def record_complete_at
self.sys[:record_complete_at]
end
def record_complete_at=(val)
if self.sys[:record_complete_at].nil? || val < self.sys[:record_complete_at]
self.sys[:record_complete_at] = val
end
end
def serialize(record, serialization_params, output_hash)
if include_attribute?(record, serialization_params)
output_hash[key] = if method.is_a?(Proc)
method.arity.abs == 1 ? method.call(record) : method.call(record, serialization_params)
else
record.public_send(method)
end
end
end
def as_indexed_json(options = {})
serializer = ProgressSerializer.new(self, {
is_collection: false,
fields: {
progress: %i[
id
name
...
]
}
})
end
rescue Elasticsearch::Transport::Transport::Error => e
Cupix::Logger.error("ElasticsearchError - #{e.message}", class: self.class.name, function: __method__)
BulkIndexWorker.perform_async(self.class.name, [id], 'index')
rescue StandardError => e
Cupix::Logger.error("StandardError - #{e.message}", class: self.class.name, function: __method__)
BulkIndexWorker.perform_async(self.class.name, [id], 'index')
end
기대 동작: 직렬화 시 record_complete_at가 인자 없이 호출되어 self.sys[:record_complete_at] 값이 반환되어야 한다.
실제 동작: fast_jsonapi가 Symbol#to_proc이 만든 Proc의 arity(-2)를 보고 2-인자 분기를 선택, record_complete_at(serialization_params)로 호출 → ArgumentError 발생.
Log Evidence#
Datadog 쿼리:
service:cupixworks-worker status:error "wrong number of arguments (given 1, expected 0)"
Same-request 컨텍스트 쿼리:
service:cupixworks-worker @request_id:3a78378665da18573e8f5297
Sidekiq death handler 로그(스택트레이스 포함):
{
"timestamp": "2026-06-08 10:26:33",
"status": "error",
"message": "Sidekiq job died after all retries",
"class": "SidekiqDeathHandler",
"function": "death_handler",
"error": {
"msg": "wrong number of arguments (given 1, expected 0)",
"stack": [
"/var/app/current/app/models/concerns/properties/progress.rb:91:in `record_complete_at'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/attribute.rb:14:in `serialize'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/serialization_core.rb:48:in `block in attributes_hash'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/serialization_core.rb:47:in `each'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/serialization_core.rb:47:in `each_with_object'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/serialization_core.rb:47:in `attributes_hash'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/serialization_core.rb:80:in `record_hash'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/object_serializer.rb:46:in `hash_for_one_record'",
"/var/app/current/vendor/bundle/ruby/3.3.0/gems/fast_jsonapi-1.5/lib/fast_jsonapi/object_serializer.rb:35:in `serializable_hash'",
"/var/app/current/app/models/concerns/searchable.rb:588:in `to_searchable_json'"
]
}
}
Trigger 컨텍스트 (같은 request_id로 직전에 발생한 Transfer 로그):
:exclamation: [Facility Transfer][854] 1단지 211동(fqgvj) from 이문1구역 주택재개발 정비사업(2912) to 주택(5719) in error.
[Transfer][854][60] Finalizing Progress on facility fqgvj
직렬화 실패 → rescue 분기 → BulkIndexWorker 재시도 흐름:
StandardError - wrong number of arguments (given 1, expected 0) (class: Progress, function: _update_document)
Index error - wrong number of arguments (given 1, expected 0) (class: Progress, function: _index_document)
NotFound - attributes_in_database (class: Progress, function: _update_document)
발생 패턴 (모두 Facility Transfer burst와 일치):
2026-06-06 20:13 ~ 22:59 KST (Transfer 854 첫 burst, 12건)
2026-06-07 21:57 KST (2건)
2026-06-08 10:22 ~ 10:26 KST (5건, 마지막에 Sidekiq dead)
코드 도입 commit (참고):
commit 1f816867e3ef8bfa3be4ce8e8f786194df53d905
Author: eddy.lee <eddy.lee@cupix.com>
Date: Tue Apr 11 10:50:01 2023 +0900
TSLA-5369 fix scroll
+ attribute :record_completed_at, &:record_complete_at
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | &:record_complete_at 형태로 등록한 직렬화 attribute가 Symbol#to_proc.arity == -2이기 때문에 fast_jsonapi 1.5의 Attribute#serialize가 serialization_params를 1-인자로 전달하여 0-인자 메서드 호출에 실패 |
스택트레이스 최상단 progress.rb:91:in 'record_complete_at' + fast_jsonapi/attribute.rb:14:in 'serialize' (Datadog death_handler 로그). progress_serializer.rb:91의 attribute :record_completed_at, &:record_complete_at 코드. fast_jsonapi attribute.rb:14의 arity.abs == 1 ? 1-arg : 2-arg 분기. as_indexed_json이 serialization_params를 비어있지 않게 넘김 (searchable/progress.rb:232) |
— | Confirmed |
| H2 | record_complete_at 메서드 시그니처가 최근 변경되어 인자 1개를 받도록 바뀌었다 |
없음 | progress.rb:91-93은 0-인자 정의이며 git log에서 최근 시그니처 변경이 없음. 동일 코드가 2023-04-11부터 존재 |
Rejected |
| H3 | Facility Transfer 코드가 직접 record_complete_at(arg)를 호출했다 |
없음 | 스택트레이스가 fast_jsonapi 직렬화 경로에서 시작되며 Transfer 코드 프레임이 호출 stack에 없음 | Rejected |
| H4 | Elasticsearch 응답 오류로 인한 우연한 메시지 일치 | 없음 | Index error 메시지가 Cupix::Logger.error("Index error - #{e.message}", ...) (searchable.rb:51)에서 만들어진 것이며, 같은 request_id의 death_handler 로그에 정확한 ArgumentError 스택이 잡힘 |
Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
- 파일:
app/serializers/progress_serializer.rb:91 - 방향:
&:record_complete_at단축 표기를 fast_jsonapi가 0-인자 호출로 분기되도록 1-인자 람다나 명시적 block 형태로 교체한다. 동일한 직렬화 결과를 유지하되 fast_jsonapi의 arity 분기에서arity.abs == 1경로를 타도록 만드는 것이 핵심이다 (예: 1-인자 람다 또는attribute(:record_completed_at) { |progress| progress.record_complete_at }형태). - 근거: fast_jsonapi 1.5
Attribute#serialize가 Proc의 arity로 호출 인자 수를 결정한다.Symbol#to_proc이 만드는 Proc의 arity는-2이므로 항상 2-인자 분기를 타게 되며, 이는Properties::Progress#record_complete_at의 0-인자 시그니처와 충돌한다. - 블록을 그냥 제거하면 안 되는 이유: serializer 키(
record_completed_at, "d" 포함)와 모델 메서드명(record_complete_at, "d" 없음)이 다르다.attribute :record_completed_at만 작성하면 fast_jsonapiobject_serializer.rb:191-195가method: :record_completed_at을 등록하고,attribute.rb:13-17의record.public_send(:record_completed_at)분기를 타서Progress에 존재하지 않는 메서드를 호출한다 (NoMethodError). 다시 말해&:record_complete_at부분은 키-메서드 이름 매핑을 담당하므로 형태만 바꿔야지(do |progress| progress.record_complete_at end또는 1-인자 람다) 삭제해서는 안 된다. 같은 파일의record_undetected_at/record_incomplete_at/record_unset_at(line 92-94)은 키와 메서드명이 일치해서 블록 없이 동작하지만,record_completed_at↔record_complete_at은 그렇지 않다. - 검증: ProgressSerializer 단위 spec에서
serializable_hash를 호출했을 때record_completed_at키가 예외 없이 반환되는지 확인. 실 데이터에 대해as_indexed_json호출이 성공하는지 통합 spec 또는 콘솔 검증.
단기 개선 (1주 이내)#
- 다른
&:-스타일 attribute 점검 (Revision 3에서 실제 검사 완료):app/serializers/전반의attribute :foo, &:bar패턴 일괄 조사 결과 다음 두 곳에 동일 패턴 위험이 추가로 존재한다. 자세한 분류는 아래 "## Other Serializers Audit" 섹션 참고.app/serializers/category_serializer.rb:26—attribute :row_order, &:id(ActiveRecord::Base#id는 0-인자, 동일 ArgumentError 가능성).app/serializers/schedule_revision_serializer.rb:35—attribute :object_key, &:object_key(ScheduleRevision#object_key(ver = nil)은 1 optional 인자라 예외는 없지만serialization_paramsHash가ver로 전달되어 잘못된 object_key 문자열을 만든다).- 그 외
&:_user,&:_team,&:_facility,&:_parent,&:_billable등 underscore-prefixed 메서드들은app/models/application_record.rb:84및app/models/concerns/cachable.rb:7에서|*args, **kwargs, &block|시그니처로 자동 정의되어 가변 인자를 받으므로 안전.
_update_document실패 재시도 루프 차단: 현재searchable.rb:118-120은StandardError전반을BulkIndexWorker로 재큐잉한다.ArgumentError처럼 입력 변화가 없으면 재시도해도 100% 실패가 보장되는 예외는 즉시 실패로 분류해 dead 큐 누적을 줄이고 알람 신호를 명확히 하도록 분기 추가를 검토.- Facility Transfer 워커 보호: Transfer 작업 도중 단일 Progress 레코드 인덱싱 실패가 transfer 자체를
in error.상태로 만드는지 여부를 확인하고, indexing 실패와 transfer 진행을 분리하는 방향 검토.
장기 개선 (재발 방지)#
- fast_jsonapi 사용 가이드라인 정립:
&:method단축 표기 대신attribute(:key) { |record| record.method }또는 1-인자 람다를 권장 표준으로 채택. 직렬화기 lint 룰(예: 커스텀 RuboCop cop 또는 grep 기반 CI 체크)로&:패턴 자체를 금지하거나 화이트리스트화. - fast_jsonapi 1.5는 2018년 이후 유지되지 않는 버전이다. 활성 메인테이너 fork (예:
jsonapi-serializer)로의 마이그레이션을 장기 로드맵에 추가.
Monitoring#
- 추가할 알림:
service:cupixworks-worker @class:Progress @function:_update_document "wrong number of arguments"발생 시 즉시 Slack 알람.service:cupixworks-worker "Sidekiq job died after all retries" @error.msg:"wrong number of arguments"알람.
- 추가할 메트릭/대시보드:
BulkIndexWorkerre-enqueue 빈도 (단위 시간당 build-up 모니터링).- Facility Transfer 작업 종료 시 인덱싱 실패 건수.
Datadog 쿼리 예시:
service:cupixworks-worker status:error @class:Progress "wrong number of arguments"
service:cupixworks-worker "[Facility Transfer]" status:error
Other Serializers Audit#
Revision 3 피드백 ("여기말고 다른 serializer 에서도 동일한 문제가 있는지 확인")에 따라 tesla/app/serializers/ 전체를 조사했다. 총 230여 개의 attribute :foo, &:bar 사용처를 분류한 결과는 아래와 같다.
분류 기준#
- Vulnerable (확실): 대상 메서드가 0-인자로 정의되어 있어
serialization_params가 인자로 전달되면ArgumentError가 확정적으로 발생. - Latent / silent bug: 대상 메서드가 1+ optional 인자를 받아 예외는 발생하지 않지만
serialization_paramsHash를 의도하지 않은 인자로 받아 잘못된 결과를 산출. - Safe (variadic): 대상 메서드가
*args, **kwargs시그니처(직접 정의 또는 메타프로그래밍)라 추가 인자를 무시하고 정상 동작.
Findings#
| # | 위치 | 패턴 | 대상 메서드 정의 | 상태 |
|---|---|---|---|---|
| 1 | app/serializers/progress_serializer.rb:91 |
attribute :record_completed_at, &:record_complete_at |
app/models/concerns/properties/progress.rb:91-93 def record_complete_at (0-인자) |
Vulnerable (확정 - 본 인시던트의 원인) |
| 2 | app/serializers/category_serializer.rb:26 |
attribute :row_order, &:id |
ActiveRecord::Base#id — Rails 7 attribute reader (0-인자) |
Vulnerable (잠재) — Category 인덱싱 시 searchable/category.rb:83-104의 as_indexed_json에 row_order가 fieldset에 포함되지 않아 평소엔 발현되지 않음. 그러나 API endpoint(api/v1/categories_controller.rb:46-67)는 @fields = params[:fields]로 fieldset을 클라이언트가 지정하게 하므로 ?fields[category]=row_order로 호출되면 즉시 ArgumentError. Datadog 14일 retention 내에서는 발현 사례 없음(service:cupixworks-api "wrong number of arguments (given 1, expected 0)" 검색 결과 0건). |
| 3 | app/serializers/schedule_revision_serializer.rb:35 |
attribute :object_key, &:object_key |
app/models/schedule_revision.rb:25 def object_key(ver = nil) — 1 optional 인자 |
Latent silent bug — record.object_key(serialization_params) 호출 시 ver = {} (또는 사용자 params)로 평가되어 line 26의 ver ? "_r#{ver}" : "_r#{revision}"이 truthy 분기를 타고 "_r{}" 등 잘못된 revision suffix가 만들어짐. 예외 없이 as_indexed_json(searchable/schedule_revision.rb:69) / Firebase sync(firebase/schedule_revision.rb:27) 양쪽에서 잘못된 object_key 필드가 인덱스에 저장될 수 있다. Datadog로는 검출 불가(예외 없음). |
| 4 | app/serializers/permitted_accessor_serializer.rb:4 |
attribute :type, &:associated_resourcable_type |
app/models/association.rb:9 belongs_to :associated_resourcable, polymorphic: true의 _type 컬럼 — Rails attribute reader (0-인자 추정) |
Potentially vulnerable, 미발현 — controllers/concerns/permitted_accessor_controller.rb는 fieldset filtering 없이 PermittedAccessorSerializer를 호출하므로 :type attribute는 항상 직렬화 경로를 탄다. 이론적으로 ArgumentError가 나야 하지만 Datadog 14일 retention 동안 0건. AR 자동 생성 attribute method가 일부 경로에서 가변 인자를 묵시적으로 수용하거나, 이 controller endpoint 호출 빈도가 매우 낮아 노출되지 않은 것으로 추정. 확정 판정에는 production console에서 record.associated_resourcable_type({})을 실행하는 검증이 필요. |
| 5 (다수) | app/serializers/*_serializer.rb 의 &:_user, &:_team, &:_facility, &:_workspace, &:_record, &:_level, &:_bim, &:_review, &:_parent, &:_billable, &:_capture, &:_default_workflow 등 underscore-prefixed 모든 패턴 (~210건) |
attribute :user, &:_user 등 |
app/models/application_record.rb:84 `define_method "_#{name}" do |
*args, **kwargs, &block |
Datadog Cross-Check#
같은 ArgumentError 패턴을 14일 retention 전체에서 조사:
service:(cupixworks-api OR cupixworks-worker) "wrong number of arguments (given 1, expected 0)"
- 결과: 42건. 모두 (a)
Progress._update_document/Progress._index_document(본 인시던트, 39건) 또는 (b)Cupix::PubSub::Subscribers::ElementRecordSynchronizer#created(lib/cupix/pub_sub/subscribers/element_record_synchronizer.rb:5-7, 3건)에서 발생. 후자는 serializer&:패턴과 무관 —def created가 0-인자로 정의되었는데 subscriber base가event인자로 호출하기 때문에 발생한 별도 버그(같은 root cause class: 0-arity 메서드에 1 인자 전달). - 따라서 현재 production traffic 기준으로 serializer
&:패턴 중 실제 외부에서 발현된 것은 progress_serializer.rb:91 한 군데뿐이지만,category_serializer.rb:26과permitted_accessor_serializer.rb:4는 잠재적 ticking bomb이며,schedule_revision_serializer.rb:35는 소리 없이 잘못된 데이터를 인덱스에 쓰고 있을 수 있다.
권장 후속 조치#
- 즉시:
progress_serializer.rb:91fix와 함께category_serializer.rb:26,schedule_revision_serializer.rb:35,permitted_accessor_serializer.rb:4도 같은 PR에서attribute(:key) { |record| record.method }형태(또는 1-인자 람다)로 함께 교체. - CI lint:
app/serializers/**/*.rb에 대해attribute\s+:\w+,\s*&:정규식을 grep하는 RuboCop cop 또는 단순 grep CI step을 추가하여 향후 재도입을 차단. - 검증 (production console 또는 spec): PermittedAccessorSerializer 의
:type이 0-인자 호출에 실제로 raise하는지 확인하여 위 표의 "potentially vulnerable" 분류를 확정/철회.
Risk Assessment#
- Risk level: medium
- 예상 복잡도: trivial (한 줄 수정)
- 영향: 수정 자체는 단순하나 fast_jsonapi의
&:패턴이 다른 serializer에도 존재할 가능성이 있어 동일 버그가 잠재. 검색 인덱스 stale 가능성으로 인해 사용자 가시 지표(검색·집계)에 영향.
Revision History#
Revision 2#
Feedback: attribute :record_completed_at, &:record_complete_at 에서 뒷부분(, &:record_complete_at)을 아예 제거해도 동작하는지 확인 요청.
판정:
| 피드백 항목 | 판정 | 근거 |
|---|---|---|
&:record_complete_at 부분을 삭제해서 attribute :record_completed_at만 남겨도 되는지 검토 |
거부 (삭제 불가) | serializer 키와 모델 메서드 이름이 다르다. 모델 메서드는 record_complete_at (no "d"); app/models/concerns/properties/progress.rb:91-99. serializer 키는 record_completed_at (with "d"); app/serializers/progress_serializer.rb:91, app/models/concerns/searchable/progress.rb:181,265. fast_jsonapi object_serializer.rb:188-196은 블록과 추가 메서드명이 모두 없으면 method: attr_name을 사용하므로 :record_completed_at이 등록된다. 그 다음 attribute.rb:13-17은 method.is_a?(Proc)가 false인 경우 record.public_send(method)를 호출 — 즉 progress.public_send(:record_completed_at)이 호출되는데, 이런 메서드는 Progress에 존재하지 않으므로 NoMethodError가 발생한다. 같은 파일의 record_undetected_at/record_incomplete_at/record_unset_at(line 92-94)은 모델 메서드명과 정확히 일치하기 때문에 블록 없이 정상 동작하지만, record_completed_at ↔ record_complete_at은 비대칭이므로 매핑 정보가 반드시 필요하다. |
변경 사항:
## Fix Recommendation > 즉시 조치 (Critical)섹션에 "블록을 그냥 제거하면 안 되는 이유" 항목을 추가하여, 키와 메서드명 비대칭 때문에 블록 자체를 삭제할 수 없고 형태만(블록/람다로) 바꿔야 한다는 점을 명시.
추가 조사 내용:
tesla/vendor/cache/fast_jsonapi-1.5.gem을 추출해lib/fast_jsonapi/object_serializer.rbattributes매크로(line 183-199) 구현 확인 — 블록과 명시적 method_name 모두 없을 때method: method_name(Symbol)이 등록됨.lib/fast_jsonapi/attribute.rb:11-19serialize에서method가 Symbol인 경우record.public_send(method)로 호출됨을 재확인.tesla레포에서record_completed_at사용처 grep — 정의된 인스턴스 메서드는 없고, ES 인덱스 필드 이름과 serializer fields 리스트에만 등장하는 것으로 확인.
Revision 3#
Feedback: "여기말고 다른 serializer 에서도 동일한 문제가 있는지 확인" — progress_serializer.rb:91 외 다른 serializer에서 같은 &:method_name arity 버그가 있는지 전수 조사 요청.
판정:
| 피드백 항목 | 판정 | 근거 |
|---|---|---|
다른 serializer에 동일한 &: arity 버그가 있는지 전수 조사 |
수용 | tesla/app/serializers/ 전체에서 attribute :foo, &:bar 패턴 ~230건을 grep으로 수집 후 각 대상 메서드 정의를 확인. 결과: (1) progress_serializer.rb:91 외에 category_serializer.rb:26 attribute :row_order, &:id (AR::Base#id 0-인자, fieldset에 row_order 포함 시 ArgumentError), schedule_revision_serializer.rb:35 attribute :object_key, &:object_key (schedule_revision.rb:25 def object_key(ver = nil) 1 optional 인자 — 예외는 없으나 serialization_params Hash가 ver로 전달되어 잘못된 string 생성), permitted_accessor_serializer.rb:4 attribute :type, &:associated_resourcable_type (association.rb:9의 polymorphic type 컬럼, AR 자동 생성 reader는 0-인자 추정 — 이론상 vulnerable이나 Datadog 14일 동안 0건 발현). (2) 그 외 ~210건의 &:_user/&:_team/&:_facility/&:_parent/&:_billable 등 underscore-prefixed 패턴은 모두 app/models/application_record.rb:84 (overridden belongs_to) 및 app/models/concerns/cachable.rb:7 (Cachable concern)에서 `define_method "#{name}" do |
변경 사항:
## Fix Recommendation > 단기 개선 (1주 이내)의 "다른&:-스타일 attribute 점검" 항목을 실제 조사 결과로 교체. 발견한 3건의 후보 위치를 명시.## Risk Assessment섹션 직전에 새 섹션## Other Serializers Audit추가 — 분류 기준, findings 표(5개 row), Datadog cross-check 결과, 권장 후속 조치 포함.
추가 조사 내용:
tesla/app/serializers/**/*.rb전체 grepattribute\s+:\w+\s*,\s*&:\w+으로 ~230건 수집.tesla/app/models/application_record.rb:81-95의 overriddenbelongs_to매크로에서define_method "_#{name}" do |*args, **kwargs, &block|확인 — 모든_<assoc>메서드가 가변 인자.tesla/app/models/concerns/cachable.rb:7define_method('_parent') do |*args, **kwargs, &block|확인.tesla/app/models/schedule_revision.rb:25def object_key(ver = nil)시그니처 확인 — silent latent bug.tesla/app/controllers/api/v1/categories_controller.rb:46-67에서@fields = params[:fields]동적 fieldset 확인 —row_order요청 시 trigger 가능.tesla/app/models/concerns/searchable/category.rb:83-104의as_indexed_json에서row_order가 fieldset에 포함되지 않음 확인 — 인덱싱 경로는 안전.tesla/app/controllers/concerns/permitted_accessor_controller.rb에서 fieldset filtering 없이 PermittedAccessorSerializer 호출 확인 —:type항상 직렬화.- Datadog 14일 retention 전수 검색:
service:(cupixworks-api OR cupixworks-worker) "wrong number of arguments (given 1, expected 0)"결과 42건, 모두 Progress 또는 ElementRecordSynchronizer(serializer 무관).