ES /docs

ForgeUrnValidator::validateForgeUrns | validation failed - {

RCA: ForgeUrnValidator::validateForgeUrns | validation failed

Overview#

What Happened#

2026-05-01 09:49:07 UTC에 cupixworks-sitetrack-instance 서비스에서 BIM 18647의 Forge URN 검증이 실패했다. sitetrack-master agent가 preprocessor가 다운로드한 bim_model.json 파일의 URN과 Tesla API에서 가져온 현재 forge_urn 값을 비교했을 때, 동일 BIM 모델에 대해 서로 다른 타임스탬프를 가진 두 개의 URN이 존재하여 불일치가 발생했다. 동일한 에러가 약 1시간 전(08:38:27 UTC)에도 발생한 것으로 확인된다.

Quick Facts#

Field Value
exception.class Error
exception.message Forge URN mismatch for BIM 18647: expected ...703317..., got ...695392...
top_frame forge-urn-validator.ts:9175 (bundled app.cjs)
env production, us-west-2

Timeline#

  1. 2026-05-01 08:38:27 UTC — 동일 BIM 18647에 대한 첫 번째 URN mismatch 에러 발생
  2. 2026-05-01 08:48:43 UTC — Sitetrack::run 시작
  3. 2026-05-01 09:49:07 UTC — ForgeUrnValidator에서 URN mismatch 에러 발생 (이 클러스터의 대표 에러)
  4. 2026-05-01 09:49:07 UTC — 에러가 4개 로그 라인으로 전파 (validateSingleBimModel → validateForgeUrns → Sitetrackservice.validateForgeUrns → Sitetrack.run)

Error Log#

Datadog Logs

text
ForgeUrnValidator::validateForgeUrns | validation failed - {
  name: 'Error',
  message: 'Forge URN mismatch for BIM 18647: expected dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGVzbGEtcHJvZHVjdGlvbi8xODY0N18xNzczODY0NzAzMzE3XzIwMjYwMzEyLUlBRDU1NCUyMEJMREctQ09NUE9TSVRFLm53ZA==, got dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGVzbGEtcHJvZHVjdGlvbi8xODY0N18xNzczODc5Njk1MzkyXzIwMjYwMzEyLUlBRDU1NCUyMEJMREctQ09NUE9TSVRFLm53ZA==',
  stack: 'Error: Forge URN mismatch for BIM 18647: ...'
}

Impact#

  • Service: cupixworks-sitetrack-instance
  • Team: clark-vdc
  • 발생 횟수: 1 (이 클러스터), 추가로 동일 에러 08:38 UTC에도 관찰됨
  • 최초 발생: 2026-05-01T09:49:07.684Z
  • 최근 발생: 2026-05-01T09:49:07.684Z

Root Cause Summary#

BIM 18647의 Forge URN이 preprocessor 단계와 master 단계 사이에 변경되어 검증이 실패했다. 구체적으로: preprocessor가 EFS에 bim_model.json을 저장할 때의 BIM revision URN(타임스탬프 1773864703317)과, master agent가 Tesla API에서 가져온 현재 forge_urn(타임스탬프 1773879695392)이 다르다. 이는 preprocessor 실행 이후, master agent 실행 전에 해당 BIM 모델에 대한 새로운 BIM revision이 생성되어 bim.forge_urn이 업데이트되었기 때문이다. 두 URN의 타임스탬프 차이는 약 4.2시간(1773879695392 - 1773864703317 = 14992075ms)으로, 이 시간 동안 BIM revision 재업로드가 발생한 것으로 추정된다.

Technical Analysis#

Code Path#

1. Preprocessor 단계 — bim_model.json 생성

preprocessor agent(SiteTrackPreprocessorRunner)가 BIM 메시를 다운로드하고 bim_model.json을 EFS에 저장한다. 이 파일에는 다운로드 시점의 forge_urnurn 필드로 포함된다.

applications/agents/packages/models/src/cpbim.ts:58-71typescript
private initialize = (): void => {
    const idStr = this.id.toString();
    this._meshArchiveFileDownloadUrl = CPX_API_ENDPOINT + '/bims/' + idStr + '/resources/mesh/download';
    const meshDirPath = this._parent.meshDirPath;
    if (meshDirPath) {
        const bimWorkspaceDirPath = path.join(meshDirPath, idStr);
        CPUtils.checkAndCreateFolder(bimWorkspaceDirPath);
        this._meshArchiveFilePath = path.join(bimWorkspaceDirPath, 'mesh.zip');
        this._bimObjectFilePath = path.join(bimWorkspaceDirPath, 'bim_objects.json');
        this._sourceInfoJsonFilePath = path.join(bimWorkspaceDirPath, 'bim_model.json');
    }
};

2. Preprocessor 단계 — request JSON 생성

preprocessor가 bim_validator_request.json을 생성할 때, Tesla API에서 가져온 현재 forge_urnbimModel.forge_urn에 설정한다.

applications/agents/packages/models/src/cpbim.ts:160-168typescript
const requestModel: IRequestModel = {
    id: this.id,
    key: this.key,
    type: 'bim',
    forge_urn: this.forgeUrn,  // Tesla API에서 온 현재 값
    bim_source: this.bimSource,
    url: this.sourceInfoJsonFilePath,
    tm: CPUtils.matrix4ToJson(bimMatrix)
};
applications/agents/packages/models/src/cpbim.ts:49typescript
get forgeUrn(): string | undefined { return this.serverModel?.forge_urn; }

3. Tesla API — forge_urn 업데이트 메커니즘

Tesla API의 BimSerializerbim.forge_urn을 반환하며, 이 값은 가장 최근 BIM revision의 forge_urn으로 업데이트된다.

app/models/concerns/statable/bim.rb:290ruby
self.forge_urn = _last_bim_revision&.forge_urn
app/serializers/bim_serializer.rb:39-50ruby
attribute :forge_urn
# ...
attribute :last_bim_revision do |bim, params|
  next if bim.last_bim_revision_id.blank?
  {
    id: bim.last_bim_revision_id,
    name: bim.respond_to?(:last_bim_revision_name) ? bim.last_bim_revision_name : nil,
    forge_urn: bim.last_bim_revision_forge_urn
  }
end

4. Master 단계 — URN 검증 실패 (Failure Point)

master agent가 시작되면, Tesla API에서 현재 sitetrack 데이터를 다시 가져오고(Sitetrackservice.runcreateCPSitetrack), preprocessor가 EFS에 저장한 bim_model.jsonurn과 API의 forge_urn을 비교한다.

  • Entry point: sitetrack-service.ts:100this.validateForgeUrns(cpSitetrack)
  • Failure point: forge-urn-validator.ts:55bimModel.forge_urn !== modelData.urn
applications/agents/packages/cupix-sitetrack-master-agent/src/forge-urn-validator.ts:52-63typescript
const modelContent = fs.readFileSync(bimModelPath, 'utf-8');
const modelData: BimModelJson = JSON.parse(modelContent);

if (bimModel.forge_urn !== modelData.urn) {
    logger.error(
        'ForgeUrnValidator::validateSingleBimModel | URN mismatch for BIM %d, requested: %s, received: %s',
        bimModel.id,
        bimModel.forge_urn,
        modelData.urn
    );
    throw new Error(`Forge URN mismatch for BIM ${bimModel.id}: expected ${modelData.urn}, got ${bimModel.forge_urn}`);
}

핵심 문제: bimModel.forge_urnbim_validator_request.json에서 읽은 값으로, preprocessor가 API를 호출한 시점의 URN이다. modelData.urnbim_model.json에서 읽은 값으로, 메시가 다운로드된 시점의 URN이다. preprocessor가 request JSON을 생성하는 시점과 메시를 다운로드하는 시점 사이, 또는 preprocessor와 master 실행 사이에 BIM revision이 변경되면 불일치가 발생한다.

실제 URN 디코딩 결과:

  • bim_model.json (expected): urn:adsk.objects:os.object:tesla-production/18647_1773864703317_20260312-IAD554%20BLDG-COMPOSITE.nwd
  • bim_validator_request.json (got): urn:adsk.objects:os.object:tesla-production/18647_1773879695392_20260312-IAD554%20BLDG-COMPOSITE.nwd

동일한 파일명(20260312-IAD554 BLDG-COMPOSITE.nwd)이지만 업로드 타임스탬프가 다르다 — 약 4.2시간 차이.

Log Evidence#

Datadog에서 사용한 쿼리:

text
service:cupixworks-sitetrack-instance status:error "ForgeUrnValidator"
text
service:cupixworks-sitetrack-instance "18647"

08:38:27 UTC — 첫 번째 발생

text
ForgeUrnValidator::validateSingleBimModel | URN mismatch for BIM 18647, requested: dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGVzbGEtcHJvZHVjdGlvbi8xODY0N18xNzczODc5Njk1MzkyXzIwMjYwMzEyLUlBRDU1NCUyMEJMREctQ09NUE9TSVRFLm53ZA==, received: dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGVzbGEtcHJvZHVjdGlvbi8xODY0N18xNzczODY0NzAzMzE3XzIwMjYwMzEyLUlBRDU1NCUyMEJMREctQ09NUE9TSVRFLm53ZA==

09:49:07 UTC — 두 번째 발생 (동일한 BIM, 동일한 URN 쌍) 에러가 4개 레벨로 전파됨:

  1. ForgeUrnValidator::validateSingleBimModel — URN mismatch 감지
  2. ForgeUrnValidator::validateForgeUrns — 에러 재throw
  3. Sitetrack::validateForgeUrns — 에러 재throw + error code AGT1813 설정
  4. Forge URN validation failed — 최종 에러 메시지

두 차례 모두 동일한 URN 쌍으로 실패하여, bim_model.json(EFS)의 내용이 변경되지 않은 상태에서 재시도가 반복되고 있음을 보여준다.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 preprocessor와 master 사이에 BIM revision이 업데이트되어 API의 forge_urn이 변경됨 URN 디코딩 결과 동일 파일명에 타임스탬프만 다름 (1773864703317 vs 1773879695392, ~4.2h 차이). Tesla API의 bim.forge_urnlast_bim_revision.forge_urn으로 자동 업데이트됨 (statable/bim.rb:290). Confirmed
H2 메시 다운로드 중 잘못된 파일이 저장됨 (네트워크 오류 등) 두 URN 모두 유효한 Autodesk OSS URN이며 동일 BIM ID와 동일 파일명을 가짐. 단순히 업로드 타임스탬프만 다르므로 파일 손상이 아닌 정상적인 revision 차이. Rejected
H3 bim_validator_request.json이 master 단계에서 재생성되어 최신 URN을 가짐 master agent의 sitetrack-service.ts에서 createCPSitetrack으로 API 재조회 후 request JSON을 읽음 — 하지만 request JSON은 preprocessor가 생성하여 EFS에 저장한 것을 읽는 것이므로, request의 forge_urn은 preprocessor 시점의 값. 로그에서 "requested" URN이 더 새로운 타임스탬프를 가짐. request JSON의 forge_urn이 실제로는 preprocessor가 API를 호출한 시점의 값이 아닌, 두 시점 중 나중 값을 포함하고 있어 master가 API를 다시 호출하여 request를 재구성했을 가능성도 있음 — uncertain, needs verification Inconclusive

Fix Recommendation#

즉시 조치 (Critical)#

  • forge-urn-validator.ts:55 — 현재 strict equality 비교를 완화하여, URN mismatch를 에러가 아닌 경고로 처리하고 처리를 계속하도록 변경. URN의 핵심 부분(bucket, BIM ID, 파일명)이 일치하면 타임스탬프 차이는 무시할 수 있음.
  • 또는 sitetrack-service.ts:196 — error code를 설정한 후 throw하는 대신, warn 로그만 남기고 처리를 계속하도록 변경.

단기 개선 (1주 이내)#

  • preprocessor와 master 간 데이터 일관성 보장 방안:
    • master 단계에서 bim_model.json의 URN이 아닌, bim_validator_request.jsonforge_urn을 기준으로 메시를 재다운로드하거나, bim_model.jsonurn 필드를 현재 API 값으로 업데이트하는 로직 추가.
    • 또는 bim_validator_request.json 생성 시 bim_model.json에서 URN을 직접 읽어 사용하여, 두 소스가 항상 동기화되도록 변경.

장기 개선 (재발 방지)#

  • preprocessor → master 파이프라인에서 BIM revision 변경 감지 메커니즘 도입. BIM revision이 변경된 경우 preprocessor부터 재실행하는 retry 로직 추가.
  • BIM revision 업로드 이벤트와 sitetrack 처리 스케줄링 간의 충돌을 방지하는 lock 또는 sequencing 메커니즘 검토.

Monitoring#

  • Forge URN mismatch 에러 발생 빈도 모니터링:
text
service:cupixworks-sitetrack-instance status:error "Forge URN mismatch"
  • BIM revision 업데이트와 sitetrack 실행 간의 시간 차이 추적을 위한 커스텀 메트릭 추가 검토.

Risk Assessment#

  • Risk level: medium
  • 예상 복잡도: standard — BIM revision 변경이 sitetrack 파이프라인 중간에 발생하는 race condition으로, 해당 BIM 모델에 대한 sitetrack 처리가 완전히 차단됨. 재시도해도 EFS의 bim_model.json이 갱신되지 않는 한 동일 에러가 반복됨.