ThreeMammals/Ocelot · error · Exception
dotnet test failed with exit code
Error message
dotnet test failed with exit code {exitCode} What it means
Thrown after 'dotnet test' (via coverlet collector) returns a non-zero exit code that is not the whitelisted code 7. Code 7 is deliberately treated as 'tests passed but background threads didn't exit cleanly' and only warns. Any other non-zero code means real test failures or a host crash.
Solutions
- Re-run the tests locally with the same arguments and inspect the failing test output.
- Fix the failing test or the regression it exposes (exit code 1 means test failure).
- Check trx/console logs for 'Test host process crashed' — fix SDK/runtime version mismatch if so.
- If the crash is thread-exit related but surfaces as a different code, add that code to the tolerated set only after verifying tests actually passed.
Example fix
// before if (exitCode != 0 && exitCode != 7) // after (only if verified non-failing) if (exitCode != 0 && exitCode != 7 && exitCode != 8)
Defensive patterns
Strategy: try-catch
Validate before calling
// verify locally before CI dotnet test ./test/Ocelot.UnitTests --collect:"XPlat Code Coverage"; echo $LASTEXITCODE
Try / catch
try { RunUnitTests(); }
catch (Exception ex) when (ex.Message.Contains("exit code")) { Warning($"Test runner failed: {ex.Message}"); throw; } Prevention
- Run the same dotnet test command locally before pushing
- Keep test host SDK versions aligned with global.json
- Treat only verified thread-exit codes (like 7) as tolerable
- Check test logs for 'Test host process crashed'
When it happens
Trigger: dotnet test exiting with codes other than 0 or 7: at least one test failed (exit 1), test host crashed, unhandled exception in a test, or collection abort.
Common situations: A flaky or genuinely failing unit test after a code change; test host process crash on .NET SDK mismatch; deadlock in tests causing abort.
AI-assisted analysis of ThreeMammals/Ocelot@d1f22d9304 (2026-09-12).
Data as JSON: /api/errors/d621ba4f3c3e2c28.
Report an issue: GitHub.
Appendix: source
Thrown at build.cake:583
*/
// Use StartProcess instead of DotNetTest for better control
var exitCode = StartProcess("dotnet", new ProcessSettings
{
Arguments = $"test \"{unitTestAssemblies}\" " +
$"--configuration {compileConfig} " +
$"--framework {tfm} " +
$"--no-restore --no-build " +
$"--verbosity {verbosity} " +
$"--results-directory \"{artifactsForUnitTestsDir}\" " +
$"--coverlet " +
$"--coverlet-include \"[Ocelot*]*\" " +
$"--coverlet-exclude \"[Ocelot.Testing]*\"",
WorkingDirectory = "."
});
// Only fail on actual test failures, not on thread exit issues
if (exitCode != 0 && exitCode != 7)
{
throw new Exception($"dotnet test failed with exit code {exitCode}");
}
else if (exitCode == 7)
{
Warning("Tests passed but background threads didn't exit cleanly (exit code 7). Ignoring.");
}
}
Information("ArtifactsForUnitTestsDir = " + artifactsForUnitTestsDir);
// Find all files matching pattern "coverage.cobertura.*.xml"
var coverageFiles = GetFiles(artifactsForUnitTestsDir.ToString() + "/coverage.cobertura.*.xml");
if (!coverageFiles.Any())
throw new Exception($"No coverage.cobertura.*.xml files found in {artifactsForUnitTestsDir}");
// Get the first matching file (or order by creation date if needed)
var coverageSummaryFile = coverageFiles.First();
Information("CoverageSummaryFile = " + coverageSummaryFile);
GenerateReport(coverageSummaryFile);
Information("##############################");
Information("# Code coverage");
View on GitHub (pinned to d1f22d9304)