Missing Lambda function in eu-central-1 region — config mismatch
RCA: UploadCpcLogWorker | Function name typo in eu-central-1 config (dc96 → dcg6)
Overview#
What Happened#
2026-05-22 03:22~04:30 UTC 사이에 eu-central-1 리전의 cupixworks-worker에서 UploadCpcLogWorker가 Lambda 함수 cupix-json-collector-dc96을 호출했으나, 실제 배포된 함수 이름은 cupix-json-collector-dcg6(Terraform-managed, 2026-05-13에 마지막 수정)이라 ResourceNotFoundException이 발생했다. 9와 g가 한 글자 차이로 오탈자가 발생한 config typo다. 동일 시간대 다른 리전(us-west-2, ap-southeast-2)의 동일 worker는 정상 동작했다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | Aws::Lambda::Errors::ResourceNotFoundException |
| exception.message | Function not found: arn:aws:lambda:eu-central-1:002596530511:function:cupix-json-collector-dc96:$LATEST |
| top_frame | app/workers/upload_cpc_log_worker.rb:24 |
| deploy | production-eu-central-1-20260519T0645Z0-3e770a15-cupixworks |
| env | production, eu-central-1 |
Timeline#
- 2026-05-22 03:22:04 UTC — 최초 에러 발생 (job 101841)
- 2026-05-22 04:30:49 UTC — 마지막 확인된 에러 (job 101845)
- 2026-05-22T04:04:12 UTC — 클러스터 대표 에러 (job 101840)
Error Log#
UploadCpcLogWorker::perform | error on job 101840 - Function not found: arn:aws:lambda:eu-central-1:002596530511:function:cupix-json-collector-dc96:$LATEST
Impact#
- Service:
cupixworks-worker - 발생 횟수: 6건 (클러스터 내 2건, 확장 검색 시 6건 확인)
- 최초 발생: 2026-05-22T03:22:04.483Z
- 최근 발생: 2026-05-22T04:30:49.092Z
- 영향: eu-central-1 리전의
create_capture_3d_reconstruction작업 완료 후 CPC JSON 수집이 실패. capture의 processing metric 데이터가 수집되지 않음. 3D reconstruction 결과 자체에는 영향 없음 (worker가 에러를 swallow).
Root Cause Summary#
tesla/config/aws.yaml의 production-eu-central-1.lambda.cpc_json_collector_function_name이 cupix-json-collector-dc96으로 잘못 기재되어 있다. 실제 eu-central-1에 Terraform으로 배포된 Lambda의 이름은 cupix-json-collector-dcg6(마지막 수정 2026-05-13)이다. suffix 3번째 문자에서 9 ↔ g 한 글자 오탈자로 인해 존재하지 않는 함수를 invoke하고, AWS SDK가 ResourceNotFoundException을 던진다. Lambda 자체나 IAM, 배포 파이프라인에는 문제가 없으며, config 값 한 글자만 고치면 즉시 해결된다.
Terraform 모듈(cupix-infrastructure/cupix-service/cpc-collector/main.tf:21)이 random_string(길이 4, 소문자+숫자)으로 suffix를 자동 생성하기 때문에 dcg6처럼 문자와 숫자가 섞인 값이 자연스럽게 나오며, 이를 tesla 애플리케이션의 정적 config YAML로 옮겨 적을 때 시각적으로 유사한 9와 g를 혼동한 사람 손 오류로 판단된다.
Technical Analysis#
Code Path#
- Entry point:
app/models/concerns/taskable/job.rb:63— ECS task 완료 후 UploadCpcLogWorker 큐잉
if self.jobable_type == 'Capture'
UploadCpcLogWorker.perform_in(3.second, self.id)
end
- Worker 실행:
app/workers/upload_cpc_log_worker.rb:5-25
def perform(id)
Cupix::Logger.info("UploadCpcLogWorker::perform | begins on job #{id}")
job = ::Job.find_by_id(id)
return if job.nil?
return if job.jobable_type != 'Capture'
job.upload_cpc_part_log
if job.kind == 'create_capture_3d_reconstruction'
capture_id = job.jobable_id
Cupix::Logger.info("UploadCpcLogWorker::perform | run cpc json collector on job #{id}, capture #{capture_id}")
Cupix::Aws::Lambda.run_cpc_json_collector(
model_name: 'captures',
model_key: capture_id
)
end
Cupix::Logger.info("UploadCpcLogWorker::perform | done on job #{id}")
rescue StandardError => e
Cupix::Logger.error("UploadCpcLogWorker::perform | error on job #{id} - #{e.message}")
end
- Lambda 호출:
lib/cupix/aws/lambda.rb:39-59
def run_cpc_json_collector(opts = {})
raise Cupix::Errors::Argument.new(code: 'ARG10001', reason: 'model_name is blank') if opts[:model_name].blank?
raise Cupix::Errors::Argument.new(code: 'ARG10001', reason: 'model_key is blank') if opts[:model_key].blank?
resp = lambda_client.invoke(
function_name: $AWS[:lambda][:cpc_json_collector_function_name],
invocation_type: 'RequestResponse',
payload: {
bucket_name: $AWS[:s3][:cpc_results_bucket_name],
service_name: Cupix::Tesla.service_name,
model_name: opts[:model_name],
model_key: opts[:model_key]
}.to_json
)
resp
rescue => e
raise e
end
- Lambda client 생성:
app/models/concerns/aws_adapter/lambda.rb:8-10
def lambda_client
Aws::Lambda::Client.new region: ENV['CUPIX_REGION'] || 'us-west-2'
end
-
Failure point:
lambda_client.invoke호출 시 AWS SDK가ResourceNotFoundException반환. worker의 rescue 블록에서 에러 메시지만 로깅하고 swallow. -
오탈자 위치:
tesla/config/aws.yaml:521— 실제 배포 이름은cupix-json-collector-dcg6이지만 config는-dc96으로 기재됨 (g↔9)
production-eu-central-1:
lambda:
cpc_json_collector_function_name: 'cupix-json-collector-dc96' # typo: should be dcg6
- 실제 배포 정의 (Terraform, random_string으로 suffix 생성):
cupix-infrastructure/cupix-service/cpc-collector/main.tf:17-60
module "lambda_function" {
source = "terraform-aws-modules/lambda/aws"
version = "8.0.1"
function_name = "cupix-json-collector-${random_string.service_key.result}"
...
}
resource "random_string" "service_key" {
length = 4
special = false
upper = false
}
- 다른 리전의 정상 config 값 (참고, 모두 4자리 소문자+숫자 무작위 suffix):
production-us-west-2: cpc_json_collector_function_name: 'cupix-json-collector-n9my'
production-ap-southeast-2: cpc_json_collector_function_name: 'cupix-json-collector-boge'
production-ap-southeast-1: cpc_json_collector_function_name: 'cupix-json-collector-xuqh'
production-eu-central-1: cpc_json_collector_function_name: 'cupix-json-collector-dc96' # ← typo
Log Evidence#
검색 쿼리:
service:cupixworks-worker status:error @environment:production "UploadCpcLogWorker::perform"
에러 로그 (6건 모두 동일 패턴):
2026-05-22T03:22:04.483Z | error | UploadCpcLogWorker::perform | error on job 101841 - Function not found: arn:aws:lambda:eu-central-1:002596530511:function:cupix-json-collector-dc96:$LATEST
2026-05-22T03:23:44.500Z | error | UploadCpcLogWorker::perform | error on job 101829 - Function not found: ...
2026-05-22T03:48:36.731Z | error | UploadCpcLogWorker::perform | error on job 101828 - Function not found: ...
2026-05-22T04:04:12.863Z | error | UploadCpcLogWorker::perform | error on job 101840 - Function not found: ...
2026-05-22T04:12:42.965Z | error | UploadCpcLogWorker::perform | error on job 101842 - Function not found: ...
2026-05-22T04:30:49.092Z | error | UploadCpcLogWorker::perform | error on job 101845 - Function not found: ...
정상 처리 로그 (동일 시간대, 다른 리전):
service:cupixworks-worker status:info "UploadCpcLogWorker::perform"
2026-05-22T04:30:13Z | info | UploadCpcLogWorker::perform | done on job 1082117
2026-05-22T04:29:31Z | info | UploadCpcLogWorker::perform | done on job 1082565
2026-05-22T04:29:15Z | info | UploadCpcLogWorker::perform | done on job 1082411
Job 101840 전체 라이프사이클:
2026-05-22T04:03:48.858Z | info | job_id: 101840, task_id: arn:aws:ecs:eu-central-1:002596530511:task/cupix-tesla-ece-eu/a237e57a1593443cb939899e7dee6356
2026-05-22T04:04:12.862Z | info | UploadCpcLogWorker::perform | begins on job 101840
2026-05-22T04:04:12.863Z | info | UploadCpcLogWorker::perform | run cpc json collector on job 101840, capture 36895
2026-05-22T04:04:12.863Z | error | UploadCpcLogWorker::perform | error on job 101840 - Function not found: arn:aws:lambda:eu-central-1:002596530511:function:cupix-json-collector-dc96:$LATEST
공통 속성:
- Host:
ip-10-1-80-125.eu-central-1.compute.internal - Deploy:
production-eu-central-1-20260519T0645Z0-3e770a15-cupixworks
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | tesla/config/aws.yaml의 eu-central-1 Lambda 함수명 오탈자 (dc96 → dcg6, 9 ↔ g) |
실제 배포된 Lambda 이름은 cupix-json-collector-dcg6 (Terraform-managed, 마지막 수정 2026-05-13); config 값은 -dc96; ARN에 config 값 그대로 사용되어 ResourceNotFoundException 발생; random_string이 생성하는 4자리 소문자+숫자 suffix에서 9/g는 시각적으로 혼동하기 쉬움 |
— | Confirmed |
| H2 | Lambda 함수 cupix-json-collector-dc96가 삭제되거나 배포 누락됨 |
AWS SDK가 ResourceNotFoundException 반환 |
사용자 확인 결과 eu-central-1에 cupix-json-collector-dcg6가 정상 배포되어 있음 (Terraform state 기준). 삭제/배포 누락이 아니라 config 오탈자 |
Rejected |
| H3 | IAM 권한 부족으로 Lambda invoke 실패 | — | IAM 권한 문제 시 AccessDeniedException 발생하지만, 실제는 ResourceNotFoundException |
Rejected |
| H4 | 일시적 AWS 장애 | — | 1시간 이상 지속적으로 실패; AWS 장애라면 다른 서비스도 영향 받아야 하나 ECS 작업은 정상 완료 | Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
tesla/config/aws.yaml:521의production-eu-central-1.lambda.cpc_json_collector_function_name값을cupix-json-collector-dc96→cupix-json-collector-dcg6로 수정 (한 글자9→g)- 배포 후 eu-central-1 리전에서
UploadCpcLogWorker로그가done상태로 마무리되는지 확인
단기 개선 (1주 이내)#
- 다른 리전 config 값도 실제 Terraform state의 Lambda 이름과 일치하는지 대조 검증 (
n9my,2cl5,uaif,boge,xuqh,dl4j,t7af,3fph,wrnq,0dxt,t5s0,cl7v등) UploadCpcLogWorker에서 Lambda 호출 실패 시 리전/함수명/capture_id를 구조화 로깅하여 재발 시 즉시 원인 식별 가능하게 개선- 현재
retry: 1이므로 config 오탈자는 재시도로 해결되지 않음.ResourceNotFoundException은 재시도 대상에서 제외하고 즉시 알람으로 승격
장기 개선 (재발 방지)#
- Config 값을 사람이 수기로 관리하지 않기: Terraform output 또는 SSM Parameter Store를 통해 실제 배포된 Lambda 이름을 tesla 런타임이 직접 조회하도록 리팩터. 수기 복사 자체를 제거하면
9/g유형의 오탈자 재발이 원천 차단됨 - 리전별 Lambda 존재 여부를 확인하는 synthetic check 또는 CloudWatch alarm 구성 — 함수가 존재하지 않으면 Errors 메트릭조차 뜨지 않으므로,
Invocations == 0 for > 1h조건으로 감시 - CI에서
tesla/config/aws.yaml의 Lambda 이름 필드를 Terraform state와 대조하는 검증 스텝 추가 검토
Monitoring#
- Lambda 함수 호출 에러 모니터링:
service:cupixworks-worker "UploadCpcLogWorker" status:error
- 리전별 정상 완료 카운트 (dashboard timeseries에서 measure/group by 사용):
service:cupixworks-worker "UploadCpcLogWorker::perform | done"
- CloudWatch 메트릭:
AWS/Lambda>Invocationsfor functioncupix-json-collector-dcg6in eu-central-1 — config 오탈자가 남아 있으면 이 실제 함수의Invocations는 0이지만 error 로그는 계속 발생. 두 지표를 나란히 비교하면 재발 시 즉시 식별 가능
Risk Assessment#
- Risk level: low
- 예상 복잡도: trivial — config YAML 한 글자 수정 후 배포. Lambda나 인프라 자체는 정상이며 Terraform 변경 불필요
Revision History#
Revision 1#
Feedback: "오타가 있어서 그런거임. 이걸로 다시 보고서 써줘 — Actually deployed in eu-central-1 → cupix-json-collector-dcg6 (Terraform-managed, last modified 2026-05-13, one char off: 9↔g)"
판정:
| 피드백 항목 | 판정 | 근거 |
|---|---|---|
실제 배포된 Lambda 이름이 cupix-json-collector-dcg6이며, config의 -dc96은 9↔g 오탈자 |
수용 | 사용자가 Terraform state 기반으로 실제 배포명을 확인해 제공. Terraform 정의(cupix-infrastructure/cupix-service/cpc-collector/main.tf:21)는 function_name = "cupix-json-collector-${random_string.service_key.result}"로 4자리 소문자+숫자 무작위 suffix를 생성하며 다른 리전 값들(n9my, 2cl5, uaif, boge 등)도 동일한 패턴 — dcg6는 이 규칙에 완전히 부합. config 값 dc96(tesla/config/aws.yaml:521)은 이 배포명을 사람이 옮겨 적는 과정에서 시각적으로 유사한 g/9를 혼동한 것으로 해석 |
| 근본 원인이 "Lambda 미배포/삭제"가 아니라 "config 오탈자" | 수용 | 위와 동일. Lambda는 정상 배포되어 있으므로 재배포/파이프라인 수정이 아니라 config 한 글자 수정이 fix |
변경 사항:
- 문서 제목·description·What Happened 을 "함수 미배포"에서 "config typo (dc96 → dcg6)"로 재작성
- Root Cause Summary 를 오탈자 시나리오로 전면 교체하고,
random_stringsuffix 생성 규칙과 시각적 혼동 근거 추가 - Technical Analysis → Code Path 에 실제 오탈자 위치(
tesla/config/aws.yaml:521), Terraform 정의(cpc-collector/main.tf:17-60), 타 리전 config 대조 블록 추가 - Hypotheses: H1을 "config 오탈자"로 재정의하고 Confirmed, 기존 H1("함수 미배포/삭제")을 H2로 강등하고 Rejected. Rev0의 잘못된 H2("config 오타" Rejected)는 삭제
- Fix Recommendation: Lambda 재배포 → config 한 글자 수정으로 교체. 재발 방지에 "Terraform output/SSM으로 자동 조회" 및 "CI에서 config↔Terraform state 대조" 추가
- Monitoring: 잘못된
| stats count by region파이프 쿼리를 제거하고(dashboard timeseries에서는 렌더링되지 않음), 실제 배포명-dcg6의 CloudWatchInvocations와 error 로그를 병행 감시하도록 변경 - Risk Assessment: medium/standard → low/trivial
추가 조사 내용:
cupix-infrastructure/cupix-service/cpc-collector/main.tf— Lambda function_name 생성 로직 확인 (random_stringlength=4, 소문자+숫자)cupix-infrastructure/cupix-aws2-eu/production/terragrunt.hcl— eu-central-1 배포 컨텍스트 확인 (cpc-collector 모듈이 이 스택에서 provisioned)tesla/config/aws.yaml— 12개 리전의cpc_json_collector_function_name값 전수 조사, 모두 4자리 소문자+숫자 suffix 패턴 확인- 저장소 전체 grep 결과
dcg6는 tesla/cupix-infrastructure 소스 어디에도 하드코딩돼 있지 않음 — 사용자 제보(Terraform state)만이 유일한 출처이므로 판정 근거는 사용자 확인 + 다른 리전 패턴 대조에 기반