Skip to content
Latchkey

MSBuild "MSB3027: could not copy ... file is locked" in CI

MSB3027 means MSBuild tried to copy an output file but the destination (or source) was held open by another process and the copy exhausted its retries. On a busy runner this is usually a transient lock from a lingering test host, antivirus scan, or a parallel build touching the same file.

What this error means

The build fails with MSB3027 naming the file and the process holding the lock, after several copy retries. It is often intermittent across runs.

dotnet
error MSB3027: Could not copy "obj/App.dll" to "bin/App.dll". Exceeded retry count of 10.
Failed. The file is locked by: "testhost (12345)"

Common causes

A lingering process holds the output file

A previous test host, a still-running app instance, or a parallel build target keeps the DLL/EXE open, so the copy cannot replace it.

On-runner scanning or indexing locks the file

Antivirus or file indexing on the runner briefly locks freshly written outputs, intermittently failing the copy.

How to fix it

Kill lingering processes and serialize the copy

  1. Ensure prior test/app processes are terminated before the build step.
  2. Avoid two jobs writing the same output directory concurrently.
  3. Re-run the job; the lock is usually gone on a fresh attempt.

Lean on auto-retry for transient locks

  1. Treat a single MSB3027 with no code change as transient and re-run.
  2. On self-healing managed runners (Latchkey), transient file-lock copy failures are retried automatically so a one-off lock does not fail the pipeline.

How to prevent it

  • Do not run multiple jobs against the same output path on one runner.
  • Stop background app/test processes before rebuilding.
  • Run CI on self-healing managed runners that auto-retry transient file-lock failures.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →