in

How to Fix MSBuild Error MSB3073 in Visual Studio

The build failed with “The command exited with code 9009” buried inside an MSB3073 error, and my first reaction was to stare at that number like it meant something specific. It doesn’t, really — MSB3073 is Visual Studio’s generic way of saying “a command your build tried to run failed,” and the actual problem is almost always one line above it in the output, not in the error code itself.

Quick Answer

  • MSB3073 means an Exec task (usually a pre-build or post-build event) returned a non-zero exit code
  • Expand the Output window, not just the Error List — the real error is in the line right before MSB3073
  • Copy the exact failing command and run it manually in a Developer Command Prompt to see the actual error
  • Common causes: incorrect file paths, missing directories, locked files, permission issues, or a missing tool
  • Exit code 9009 specifically means the command or executable couldn’t be found at all

Why MSB3073 Happens

This error is intentionally generic, because it’s really just MSBuild reporting that something it launched didn’t succeed — the actual cause lives entirely in what that something was trying to do.

Incorrect paths are probably the most common root cause. Pre-build and post-build event commands reference file paths, and if a path is wrong, uses the wrong slash direction, or references a variable like $(IntDir) when $(OutDir) was actually needed, the command fails immediately before it ever does its real job.

Missing files or directories trip this up constantly. If a build event command expects an output folder to already exist and it doesn’t — because this is a fresh clone, a clean build, or a CI environment that doesn’t mirror your local setup — the command fails with a non-zero exit code that MSBuild then reports as MSB3073.

Locked files are a sneaky one. Antivirus software, a previous build process still running, or a test runner holding a file open can all block a command from writing where it needs to, and the resulting failure surfaces here even though the underlying cause has nothing to do with your project file itself.

There’s a specific exit code worth knowing on sight: exit code 9009. That number specifically means the command or executable simply wasn’t found — a typo in the path, a tool that isn’t installed, or a PATH environment variable that doesn’t include what the command needs.

Where This Shows Up Most

Custom build events (pre-build, post-build, or custom targets in .csproj/.targets files) are where this error originates almost every time, since MSBuild’s Exec task is exactly what runs those commands.

CI/CD pipelines surface this more than local builds because CI environments often lack tools, paths, or environment variables that exist on a developer’s machine by default, so a build event that works fine locally can fail immediately in a pipeline.

Projects using external tools like code signing utilities, packaging tools, or custom code generators hit this whenever the tool’s own internal error gets wrapped and reported as a generic MSBuild failure rather than a clear tool-specific message.

Cause Comparison Table

SymptomLikely CauseFix
Exit code 9009Command/tool not foundCheck path, install missing tool, verify PATH
Exit code 1 (or other nonzero) with a visible tool error above itThe tool itself failedRead the tool’s own error output, fix that specifically
Works locally, fails in CIMissing environment setup in CIMatch CI environment to local (paths, tools, variables)
Intermittent, not consistentFile lock from antivirus/previous processClose conflicting process, add antivirus exclusion
Fails only on clean buildMissing output directoryAdd mkdir or CreateDirectory step before the command

Step-by-Step Fixes

Step 1: Expand the Output window, not just the Error List. The Error List often just shows the final MSB3073 summary. View > Output, then set the dropdown to Build, and look at the full text — the actual failing command and its exit code are shown right there, usually with more context immediately above the MSB3073 line.

Step 2: Copy the exact command and run it manually. Open a Developer Command Prompt for Visual Studio, paste the exact command MSBuild tried to run (including the full path and arguments), and run it directly. The console output from running it manually is almost always clearer than what gets surfaced through the build system.

Step 3: Check the build event that’s failing. Right-click the project > Properties > Build Events, and look at both Pre-Build and Post-Build event command lines. Compare the paths and variables used there against what actually exists in your project structure.

Step 4: Verify all referenced paths and directories exist. If the command writes to or reads from a specific folder, confirm that folder actually exists at build time. Add an explicit directory creation step before the command if there’s any chance the folder might not exist yet on a fresh build.

Step 5: Check for exit code 9009 specifically. If you see this exact code, the tool or command itself wasn’t found. Verify the full path is correct, the tool is actually installed on this machine, and if you’re relying on PATH, confirm the relevant directory is actually in it for the account running the build.

Step 6: Enable diagnostic-level build logging. Tools > Options > Projects and Solutions > Build and Run, set MSBuild project build output verbosity to Detailed or Diagnostic, then reproduce the build. This gives you a much fuller picture of exactly what ran and in what order before the failure.

Step 7: Check for locked files if the failure is inconsistent. If the same build sometimes succeeds and sometimes fails with no code changes, suspect antivirus software or a leftover process holding a file open. Try closing other instances of the app being built, or temporarily disabling real-time antivirus scanning for the build output folder to confirm.

What Actually Worked For Me

I assumed the error was something wrong with my project file configuration, since that’s usually where I go looking first for build errors. Spent a while checking .csproj settings that had nothing to do with the actual problem. The Output window told me plainly, once I actually expanded it properly instead of just glancing at the Error List, that the post-build event was trying to copy a file from a folder that didn’t exist yet on a clean checkout.

The actual fix was one line — adding a directory creation step before the copy command in the post-build event. Felt almost anticlimactic after how long I’d spent assuming it was something more structurally wrong. That said, I’ve also hit MSB3073 from a genuinely locked file once, where the fix was just closing a leftover debug session that had the output DLL open, and no amount of staring at build events would’ve caught that one without noticing the pattern of “it only fails right after debugging.”

Advanced Fixes and Edge Cases

Use binary logging for large or complex projects. Running the build with the -bl flag creates a binary log that can be opened in the MSBuild Structured Log Viewer, which makes tracing exactly what happened before the failure far easier than scrolling through plain text output on big solutions.

Set the MSBuildDebugEngine environment variable for maximum detail. Setting this to 1 produces the most complete possible logging MSBuild can generate, useful specifically when diagnostic verbosity alone isn’t giving you enough to pin down the cause.

Reproduce the exact CI environment locally if the failure only happens in a pipeline. Match the same base image, user context, and environment variables your CI system uses, since a command that works with your local PATH and installed tools can fail entirely in a more minimal CI environment.

Prevention Tips

Avoid relying on PATH for build event commands where possible — use full explicit paths instead, since PATH differences between developer machines and CI environments are a common source of this exact error. Add explicit directory creation steps before any build event command that writes to a folder that might not exist on a clean checkout. And keep build event commands as simple as possible; complex chained commands make it much harder to isolate which specific step failed when MSB3073 shows up.

MSBuild Error MSB3073

FAQ

Does MSB3073 always mean my code has a bug? No. It almost always means a build event or external tool command failed, which is usually unrelated to whether your actual source code compiles correctly.

What does exit code 9009 mean specifically? The command or executable couldn’t be found at all — check the path and confirm the tool is actually installed and accessible.

Why does the same build sometimes work and sometimes fail? Intermittent MSB3073 failures often point to file locks from antivirus software or a leftover process, rather than anything wrong with your project configuration.

Is it safe to just remove the failing build event to make the error go away? Only if you understand what that build event was actually doing. Removing it silences the error but may skip something your build genuinely needs, like a code signing step or file copy.

Editor’s Opinion

the number itself tells you basically nothing, which took me an annoyingly long time to accept. the output window has the actual answer nearly every time, i just wasnt looking in the right pane. if youre stuck on this, stop staring at the error code and go find the line right above it, thats where the real story is.

Written by ugur

Ugur is an editor and writer at (NSF Tech), specializing in technology and Windows. He produces in-depth, well-researched, and reliable stories with a strong focus on Windows, emerging technologies, digital culture, cybersecurity, AI developments, and innovative solutions shaping the future. His work aims to inform, inspire, and engage readers worldwide with accurate reporting and a clear editorial voice.

Contact: [email protected]