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#
- 2026-05-01 08:38:27 UTC — 동일 BIM 18647에 대한 첫 번째 URN mismatch 에러 발생
- 2026-05-01 08:48:43 UTC — Sitetrack::run 시작
- 2026-05-01 09:49:07 UTC — ForgeUrnValidator에서 URN mismatch 에러 발생 (이 클러스터의 대표 에러)
- 2026-05-01 09:49:07 UTC — 에러가 4개 로그 라인으로 전파 (validateSingleBimModel → validateForgeUrns → Sitetrackservice.validateForgeUrns → Sitetrack.run)
Error Log#
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_urn이 urn 필드로 포함된다.
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_urn을 bimModel.forge_urn에 설정한다.
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)
};
get forgeUrn(): string | undefined { return this.serverModel?.forge_urn; }
3. Tesla API — forge_urn 업데이트 메커니즘
Tesla API의 BimSerializer는 bim.forge_urn을 반환하며, 이 값은 가장 최근 BIM revision의 forge_urn으로 업데이트된다.
self.forge_urn = _last_bim_revision&.forge_urn
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.run → createCPSitetrack), preprocessor가 EFS에 저장한 bim_model.json의 urn과 API의 forge_urn을 비교한다.
- Entry point:
sitetrack-service.ts:100—this.validateForgeUrns(cpSitetrack) - Failure point:
forge-urn-validator.ts:55—bimModel.forge_urn !== modelData.urn
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_urn은 bim_validator_request.json에서 읽은 값으로, preprocessor가 API를 호출한 시점의 URN이다. modelData.urn은 bim_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.nwdbim_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에서 사용한 쿼리:
service:cupixworks-sitetrack-instance status:error "ForgeUrnValidator"
service:cupixworks-sitetrack-instance "18647"
08:38:27 UTC — 첫 번째 발생
ForgeUrnValidator::validateSingleBimModel | URN mismatch for BIM 18647, requested: dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGVzbGEtcHJvZHVjdGlvbi8xODY0N18xNzczODc5Njk1MzkyXzIwMjYwMzEyLUlBRDU1NCUyMEJMREctQ09NUE9TSVRFLm53ZA==, received: dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6dGVzbGEtcHJvZHVjdGlvbi8xODY0N18xNzczODY0NzAzMzE3XzIwMjYwMzEyLUlBRDU1NCUyMEJMREctQ09NUE9TSVRFLm53ZA==
09:49:07 UTC — 두 번째 발생 (동일한 BIM, 동일한 URN 쌍) 에러가 4개 레벨로 전파됨:
ForgeUrnValidator::validateSingleBimModel— URN mismatch 감지ForgeUrnValidator::validateForgeUrns— 에러 재throwSitetrack::validateForgeUrns— 에러 재throw + error codeAGT1813설정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_urn은 last_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.json의forge_urn을 기준으로 메시를 재다운로드하거나,bim_model.json의urn필드를 현재 API 값으로 업데이트하는 로직 추가. - 또는
bim_validator_request.json생성 시bim_model.json에서 URN을 직접 읽어 사용하여, 두 소스가 항상 동기화되도록 변경.
- master 단계에서
장기 개선 (재발 방지)#
- preprocessor → master 파이프라인에서 BIM revision 변경 감지 메커니즘 도입. BIM revision이 변경된 경우 preprocessor부터 재실행하는 retry 로직 추가.
- BIM revision 업로드 이벤트와 sitetrack 처리 스케줄링 간의 충돌을 방지하는 lock 또는 sequencing 메커니즘 검토.
Monitoring#
- Forge URN mismatch 에러 발생 빈도 모니터링:
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이 갱신되지 않는 한 동일 에러가 반복됨.