TeamCity 2026 - migration of Artifacts from local to S3 always fails, but new builds correctly push to S3

Hi all, I am really hoping that somebody can provide some insight into this issue.

To provide some background, we have a TeamCity server hosting around 20 build configurations - these have been working well, but all of the build assets are stored locally in the default folder: C:\ProgramData\JetBrains\TeamCity\system\assets

We now have over 14GB of assets, of course we will be cleaning this up a bit - but we want to move them all to S3.  I have now configured an AWS connection and set all of the projects to push any new artifacts to an S3 bucket - this is working perfectly.  So I am now trying to migrate the existing artifacts, I found the artifacts migration tool and configured it as per the documentation - ran it and it finds the projects and builds that should be migrated to S3…and that is where the problems leave me stranded.

Every single attempt to copy a file from local to the S3 bucket fail with this set of error messages:

[2026-05-19 10:43:13,461]  DEBUG [artifact-copying-1] migration.storage.s3.S3Storage - [REDACTED_Staging:REDACTED_Staging_WebSIte:13715] [] - Calling [jetbrains.buildServer.artifacts.migration.storage.CloudStorage$$Lambda/0x00000195cf44f440@23f8bdcc], attempt: 1.
[2026-05-19 10:43:13,482]  DEBUG [artifact-copying-1] migration.storage.s3.S3Storage - [REDACTED_Staging:REDACTED_Staging_WebSIte:13715] [] - Calling [jetbrains.buildServer.artifacts.migration.storage.CloudStorage$$Lambda/0x00000195cf44f440@23f8bdcc], retry: 1 failed with exception.
java.lang.RuntimeException: Forbidden (Service: Amazon S3; Status Code: 403; Error Code: 403 Forbidden; Request ID: REDACTED; S3 Extended Request ID: REDACTED; Proxy: null)
	at jetbrains.buildServer.util.retry.RetrierImpl.asRuntimeException(RetrierImpl.java:97)
	at jetbrains.buildServer.util.retry.RetrierImpl.execute(RetrierImpl.java:41)
	at jetbrains.buildServer.artifacts.migration.storage.CloudStorage.upload(CloudStorage.kt:159)
	at jetbrains.buildServer.artifacts.migration.ProjectProcessor.copy(ProjectProcessor.kt:351)
	at jetbrains.buildServer.artifacts.migration.ProjectProcessor.access$copy(ProjectProcessor.kt:30)
	at jetbrains.buildServer.artifacts.migration.ProjectProcessor$copy$1$1$1$1.invokeSuspend(ProjectProcessor.kt:275)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: jetbrains.buildServer.artifacts.migration.storage.StorageOperationException: Forbidden (Service: Amazon S3; Status Code: 403; Error Code: 403 Forbidden; Request ID: REDACTED; S3 Extended Request ID: REDACTED; Proxy: null)
	at jetbrains.buildServer.artifacts.migration.storage.s3.S3Storage.executeWithErrorHandling(S3Storage.kt:67)
	at jetbrains.buildServer.artifacts.migration.storage.s3.S3Storage.doesArtifactExist(S3Storage.kt:104)
	at jetbrains.buildServer.artifacts.migration.storage.CloudStorage.uploadOne(CloudStorage.kt:183)
	at jetbrains.buildServer.artifacts.migration.storage.CloudStorage.upload$lambda-4$lambda-3(CloudStorage.kt:159)
	at jetbrains.buildServer.util.retry.RetrierImpl.execute(RetrierImpl.java:37)
	... 12 common frames omitted
Caused by: com.amazonaws.services.s3.model.AmazonS3Exception: Forbidden (Service: Amazon S3; Status Code: 403; Error Code: 403 Forbidden; Request ID: REDACTED; S3 Extended Request ID: REDACTED; Proxy: null)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1880)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1418)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1387)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1157)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:814)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:781)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:755)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:715)
	at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:697)
	at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:561)
	at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:541)
	at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:5558)
	at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:5505)
	at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:1403)
	at com.amazonaws.services.s3.AmazonS3Client.getObjectMetadata(AmazonS3Client.java:1377)
	at com.amazonaws.services.s3.AmazonS3Client.doesObjectExist(AmazonS3Client.java:1458)
	at jetbrains.buildServer.artifacts.migration.storage.s3.S3Storage$doesArtifactExist$1.invoke(S3Storage.kt:105)
	at jetbrains.buildServer.artifacts.migration.storage.s3.S3Storage$doesArtifactExist$1.invoke(S3Storage.kt:104)
	at jetbrains.buildServer.artifacts.migration.storage.s3.S3Storage.executeWithErrorHandling(S3Storage.kt:62)
	... 16 common frames omitted

Please keep in mind I have redacted ID's and Bucket names.

I know it's throwing a 403 error - but I cannot work out why it's throwing said error.  The TeamCity server can talk to S3, the TeamCity Build Agents are uploading to S3…it is ONLY the Migration Tool that is failing to upload to S3.

Any help or insight would be greatly appreciated - I don't want to have to build my own Migration tool for what is going to be, I hope, a one-off operation.

0
2 comments
Hi Steve,

Thanks for the detailed report and the stack trace。

The behavior you are seeing seems a known configuration gap rather than a bug in the migration tool itself. The bundled artifacts migration tool runs as a separate JVM process and does not reuse the TeamCity AWS Connection that your S3 artifact storage feature is configured with.

That is why your agents and your new builds happily push to S3 (they go through the server and use the AWS Connection), while the migration tool gets a 403 on its very first call.

Please refer to [Artifacts Migration Tool](https://www.jetbrains.com/help/teamcity/artifacts-migration-tool.html#AWS+S3) — AWS S3 to get the details of how to configure it properly.

If the 403 still appears after the credentials are in place, please share the migration tool log (with bucket name and account ID still redacted is fine) and confirm which option you went with, and we will take another look.

Files can be uploaded via https://uploads.jetbrains.com/. Please let us know the exact id after the upload.

1

Hi Tom,

Thank you for the response - I didn't realise that the Migration Tool uses the AWS CLI credentials file...which we had on the server but for a different IAM which led to the 403 error.

I replaced the credentials in that file and it worked flawlessly - in fact too fast!  14GB went up in just a few seconds…but I checked and it has indeed all gone up.

Many thanks for your help :)

0

Please sign in to leave a comment.