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.
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.
dotnet clean
# or force-remove if clean cannot
rm -rf **/obj **/bin
dotnet build -c ReleaseDo not cache obj/bin across builds
- Cache the NuGet global packages folder, not
obj/bin, which are build outputs. - Ensure checked-out files are writable (avoid read-only restores into the build tree).
- Use a clean workspace per job so stale incremental state cannot persist.
How to prevent it
- Never cache
obj/binbetween CI runs - only cache the NuGet packages folder. - Start jobs from a clean workspace to avoid stale incremental state.
- Run
dotnet cleanbefore a release build when incremental state is suspect.