ES /docs

MeshService::run | error: {"stack":"ExpiredToken: The provided token has expired.

RCA: MeshService::run | ExpiredToken: The provided token has expired

Overview#

What Happened#

2026-05-22 19:11:15 KST, cupixworks-any-mesh-agent 서비스에서 BIM mesh 추출 후 S3 업로드 중 AWS STS 임시 토큰이 만료되어 ExpiredToken 에러가 발생했다. BIM ID 18044의 mesh archive 업로드가 약 4시간 동안 진행되면서 Tesla API에서 발급받은 임시 자격증명의 유효기간을 초과했다.

Quick Facts#

Field Value
exception.class ExpiredToken
exception.message The provided token has expired.
top_frame aws-sdk/lib/services/s3.js:712
runtime Node.js (aws-sdk@2.1599.0)
env production, us-west-2

Timeline#

  1. 2026-05-22 14:53:58 KST — SQS 메시지 수신 (BIM id: 18044)
  2. 2026-05-22 15:10:17 KST — S3 업로드 시작 (mesh archive: /tmp/workspace/18044/mesh_archive/18044.zip)
  3. 2026-05-22 19:11:15 KST — S3 업로드 실패 (ExpiredToken, 약 4시간 경과)
  4. 2026-05-22 19:11:16 KST — 워크스페이스 정리 및 SQS 메시지 삭제

Error Log#

Datadog Logs

text
MeshService::run | error: {"stack":"ExpiredToken: The provided token has expired.
    at Request.extractError (/tmp/agent/dist/node_modules/.pnpm/aws-sdk@2.1599.0/node_modules/aws-sdk/lib/services/s3.js:712:35)
    at Request.callListeners (/tmp/agent/dist/node_modules/.pnpm/aws-sdk@2.1599.0/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/tmp/agent/dist/node_modules/.pnpm/aws-sdk@2.1599.0/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/tmp/agent/dist/node_modules/.pnpm/aws-sdk@2.1599.0/node_modules/aws-sdk/lib/request.js:686:14)
    at Request.transition (/tmp/agent/dist/node_modules/.pnpm/aws-sdk@2.1599.0/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/tmp/agent/dist/node_modules/.pnpm/aws-sdk@2.1599.0/node_modules/aws-sdk/lib/state_machine.js:14:12)","message":"The provided token has expired.","code":"ExpiredToken","region":null,"name":"ExpiredToken","time":"2026-05-22T10:11:15.962Z","requestId":"8H25DQC71K6CFB0D","extendedRequestId":"v5zjP4f/7bIwXWtfZhBrKiZ/rvlh16PRNAQGM+FvQxLZU/BJtqAVK8DEaLKgdv2ZGPhaIVVig6I=","statusCode":400,"retryable":true}

Impact#

  • Service: cupixworks-any-mesh-agent
  • Team: gad
  • 발생 횟수: 1
  • 최초 발생: 2026-05-22T10:11:15.967Z
  • 최근 발생: 2026-05-22T10:11:15.967Z

Root Cause Summary#

Tesla API에서 발급받은 STS 임시 자격증명(session token)으로 S3 업로드를 시작했으나, mesh archive 파일 크기가 매우 커서 업로드에 약 4시간이 소요되었다. AwsS3Manager에는 토큰 만료 시 자동 갱신하는 checkToken 메커니즘이 존재하지만, MeshService에서 setApiCreateCredentials를 호출하지 않아 _createCredentialsundefined로 남아 있어 토큰 갱신이 불가능했다. 또한 checkToken은 업로드 시작 전에만 1회 호출되므로, 업로드 도중 토큰이 만료되는 경우를 처리할 수 없다.

Technical Analysis#

Code Path#

  • Entry point: mesh-service.ts:101MeshService.run(targetId)
  • 1단계: Forge 인증 + mesh 추출 + archive 생성 (14:53 ~ 15:10, 약 17분)
  • 2단계: uploadMeshArchiveFileByCPBimuploadBimMeshArchiveFile 호출
  • Failure point: aws-s3.manager.ts:98-111s3.upload() 콜백에서 ExpiredToken 에러 수신
packages/cupix-tesla-mesh-agent/src/mesh-service.ts:254-289typescript
private uploadBimMeshArchiveFile = async (cpBim: CPBim): Promise<void> => {
    if (cpBim.meshArchiveFilePath ===  undefined) {
        throw new Error('MeshService::uploadBimMeshArchiveFile - not found mesh');
    }

    this.awsS3Manager.resetS3Info();  // _createCredentials = undefined로 초기화
    const s3Credentials = await this.createMeshResourceCredentials(cpBim);

    // ... credential 검증 ...

    this.awsS3Manager.setCredentials({
        accessKeyId: s3Credentials.aws_access_key_id,
        secretAccessKey: s3Credentials.aws_secret_access_key,
        sessionToken: s3Credentials.aws_session_token,
        expires_at: s3Credentials.expires_at,
        endpoint: s3Credentials.endpoint
    });

    await this.awsS3Manager.uploadFileStreamToS3({
        bucketName: s3Credentials.bucket_name,
        bucketKeyPath: s3Credentials.basepath,
        targetFilePath: cpBim.meshArchiveFilePath,
        acl: s3Credentials.acl
    });
};

resetS3Info() 호출로 _createCredentialsundefined가 되며, 이후 setApiCreateCredentials를 호출하지 않으므로 토큰 갱신 경로가 비활성화된다.

packages/base/src/manager/aws-s3.manager.ts:61-80typescript
private checkToken = async () => {
    let isExpired = false;
    if (this.tokenExpiresAt != undefined) {
        const now = new Date().getTime();
        const expiresTimeStamp = new Date(this.tokenExpiresAt).getTime();
        isExpired = expiresTimeStamp - 600 * 1000 < now;
    }
    if (!isExpired || this._createCredentials == undefined) {
        return;  // _createCredentials가 undefined이므로 만료되어도 갱신 불가
    }

    const _credentials = await this._createCredentials();
    this.setCredentials({
        accessKeyId: _credentials.aws_access_key_id,
        secretAccessKey: _credentials.aws_secret_access_key,
        sessionToken: _credentials.aws_session_token,
        expires_at: _credentials.expires_at,
        endpoint: _credentials.endpoint
    });
};

checkTokenuploadFileStreamToS3 시작 시 1회만 호출된다(aws-s3.manager.ts:91). 업로드 스트림이 진행되는 동안에는 토큰 상태를 확인하지 않으며, AWS SDK v2의 s3.upload()는 내부적으로 multipart upload를 수행하지만 자격증명 갱신 콜백을 지원하지 않는다.

Log Evidence#

사용한 Datadog 쿼리:

text
service:cupixworks-any-mesh-agent "18044"

타임라인 로그:

text
2026-05-22 14:53:58 KST | info | BaseService::runByMessage | id: 18044
2026-05-22 15:10:17 KST | info | AwsS3Manager::uploadFileStreamToS3 | begin - filePath: /tmp/workspace/18044/mesh_archive/18044.zip, bucketPath: cupixworks-source-b169da1a0187-mece1/resources/zyn5iw/mece1/v15
2026-05-22 19:11:15 KST | error | AwsS3Manager::uploadFileStreamToS3 | failed: resources/zyn5iw/mece1/v15 - {"message":"The provided token has expired.","code":"ExpiredToken",...}
2026-05-22 19:11:15 KST | error | MeshService::run | error: {"stack":"ExpiredToken: The provided token has expired....",...,"retryable":true}
2026-05-22 19:11:16 KST | info | BaseService::cleanUpAnythingRelatedModel | path: /tmp/workspace/18044

업로드 시작(15:10:17)부터 실패(19:11:15)까지 약 3시간 58분 소요. AWS STS 세션 토큰의 기본 유효기간은 1시간(최대 12시간 설정 가능)이므로, 토큰이 업로드 중간에 만료됨.

text
service:cupixworks-any-mesh-agent "setCredentials"

같은 시간대에 setCredentials가 실패한 작업에 대해 호출된 기록이 없음 — 토큰 갱신 시도 자체가 발생하지 않았음을 확인.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 STS 토큰 유효기간 초과 (대용량 파일 업로드 시간 > 토큰 TTL) 업로드 시작~실패 간 4시간 경과 (로그 타임스탬프). checkToken_createCredentials가 미설정. AWS 응답 statusCode:400, retryable:true Confirmed
H2 Tesla API의 credential 발급 자체가 만료된 토큰을 반환 업로드 시작 시점(15:10)에는 정상 동작했을 것 (즉시 실패했다면 더 빠른 에러 발생). 같은 시간대 다른 작업들은 정상 업로드 완료됨 (18:05~18:27) Rejected
H3 네트워크 이슈로 업로드 지연 후 토큰 만료 4시간 소요는 비정상적으로 길며 네트워크 문제일 가능성 있음 파일이 대용량 mesh archive일 수 있음. 별도의 네트워크 에러 로그 없음 (순수 ExpiredToken만 발생) Inconclusive

Fix Recommendation#

즉시 조치 (Critical)#

  • packages/cupix-tesla-mesh-agent/src/mesh-service.ts:259resetS3Info() 호출 후 setApiCreateCredentials를 등록하여 업로드 중 토큰 갱신이 가능하도록 수정
  • uploadBimMeshArchiveFile 메서드에서 credential 팩토리 함수를 AwsS3Manager에 등록:
    typescript
    this.awsS3Manager.setApiCreateCredentials(() => this.cupixApi.bim.createResourceUploadCredentials(cpBim.id, 'mesh'));
    

단기 개선 (1주 이내)#

  • AwsS3Manager.uploadFileStreamToS3에서 S3 multipart upload 사용 시 각 파트 업로드 전 checkToken 호출하도록 개선. 현재는 업로드 시작 전 1회만 호출됨
  • 대용량 파일 업로드 시 AWS SDK v3의 @aws-sdk/lib-storage 패키지 활용을 검토 — 내장 credential refresh 지원

장기 개선 (재발 방지)#

  • AWS SDK v2에서 v3로 마이그레이션 (v2는 2025-09-08 EOL). SDK v3의 credential provider chain은 자동 갱신 지원
  • 업로드 전 파일 크기 기반으로 예상 소요 시간을 계산하고, 토큰 유효기간보다 길면 multipart upload with credential refresh 전략을 자동 선택하는 로직 추가

Monitoring#

  • 추가할 메트릭: S3 업로드 소요 시간 추적 (시작~완료 간 duration)
  • Datadog 알림 쿼리:
text
service:cupixworks-any-mesh-agent "ExpiredToken"
text
service:cupixworks-any-mesh-agent "uploadFileStreamToS3 | failed"
  • STS 토큰 만료까지 남은 시간이 10분 미만인 상태에서 업로드를 시작하는 경우 warn 로그 추가 권장

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: standard
  • 1건 발생이며 대용량 BIM mesh에서만 재현 가능. 같은 시간대 다른 작업은 정상 완료됨. 그러나 수정 없이는 대용량 모델에서 반복 발생 가능.