Skip to content
Latchkey

MSBuild "MSB3021: Unable to copy" Stale Incremental State in CI

MSBuild could not copy a file during build, often because a stale or read-only obj/bin from a cached/partial earlier build left the incremental state inconsistent. A clean rebuild resolves it.

What this error means

Build fails with MSB3021: Unable to copy file, frequently after restoring a build cache or re-running on a dirty workspace. A dotnet clean (or wiping obj/bin) followed by a rebuild succeeds, pointing at stale state.

MSBuild output
error MSB3021: Unable to copy file "obj/Release/net8.0/MyApp.dll" to
"bin/Release/net8.0/MyApp.dll". Access to the path 'bin/Release/net8.0/MyApp.dll' is denied.

Common causes

Stale/read-only output from a cached build

A restored build cache (or files checked out read-only) leaves obj/bin in a state the new build cannot overwrite, so the copy is denied.

Partial or interrupted previous build

A build killed mid-copy (timeout, OOM) leaves inconsistent incremental state that the next build trips over.

How to fix it

Clean and rebuild

Wipe the stale output so the build regenerates it from scratch.

Terminal
dotnet clean
# or force-remove if clean cannot
rm -rf **/obj **/bin
dotnet build -c Release

Do not cache obj/bin across builds

  1. Cache the NuGet global packages folder, not obj/bin, which are build outputs.
  2. Ensure checked-out files are writable (avoid read-only restores into the build tree).
  3. Use a clean workspace per job so stale incremental state cannot persist.

How to prevent it

  • Never cache obj/bin between CI runs - only cache the NuGet packages folder.
  • Start jobs from a clean workspace to avoid stale incremental state.
  • Run dotnet clean before a release build when incremental state is suspect.

Frequently asked questions

What causes ""MSB3021: Unable to copy file""?
A restored build cache (or files checked out read-only) leaves obj/bin in a state the new build cannot overwrite, so the copy is denied.
How do I fix "MSB3021: Unable to copy file"?
Wipe the stale output so the build regenerates it from scratch.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card