Unity-Technologies/UnityCsReference · error · InvalidOperationException
{toolName} does not appear to be built in {il2CppFolder}
Error message
{toolName} does not appear to be built in {il2CppFolder} What it means
Thrown when locating an IL2CPP tool (e.g. il2cpp.exe) inside a development/source checkout of the IL2CPP folder. The code searches <il2CppFolder>/<toolName>/bin recursively for an executable matching the expected name; if zero candidates are found it assumes the tool was never built there.
Source
Thrown at Editor/Mono/BuildPipeline/Il2Cpp/IL2CPPUtils.cs:589
if (isDevelopmentLocation)
{
// Locating the correct development build to use is a little tricky. Complications come from
// 1) We don't know if the Debug or Release build is desired. To overcome this we will pick whichever was modified most recently
// 2) We don't know if the published or non-published build is desired. Again, we'll use whichever was modified most recently
// 3) Published builds for all platforms may or may not be built. We need to make sure not to pick a build for a different platform
// Note that this logic will intentionally avoid checking for an expected TFM. This is a dev build. Using w/e is newest is probably
// the most robust and maintainable approach.
var toolBinDirectory = Path.Combine(il2CppFolder, toolName, "bin").ToNPath();
#pragma warning disable UA2001 // The Banned API Analyzer produces compile errors for any new Linq code. This pre-existing usage has been suppressed, but should be rewritten if possible.
var candidates = toolBinDirectory.Files($"*{expectedToolExecutableName}", recurse: true)
#pragma warning restore UA2001
.OrderByDescending(f => f.GetLastWriteTimeUtc())
.ToArray();
if (candidates.Length == 0)
throw new InvalidOperationException($"{toolName} does not appear to be built in {il2CppFolder}");
var expectedPublishDirectoryName = BinaryDirectoryForPlatform(platform).ToNPath();
foreach (var candidate in candidates)
{
// Examples :
// 1) il2cpp/bin/Release/<tfm>/il2cpp.exe
// 2) il2cpp/bin/Debug/<tfm>/il2cpp.exe
if (candidate.Parent.Parent.Parent.FileName == "bin")
{
// Found a non-published build
return candidate.ToString();
}
// Examples :
// 1) il2cpp/bin/Release/<tfm>/<platform dir>/publish/il2cpp.exe
// 2) il2cpp/bin/Debug/<tfm>/<platform dir>/publish/il2cpp.exe
if (candidate.Parent.FileName == "publish" && candidate.Parent.Parent.FileName == expectedPublishDirectoryName)View on GitHub (pinned to 225b0fbdb5)
Solutions
- Build the IL2CPP toolchain in the dev enlistment (e.g. run the bee/build script that produces <toolName>/bin/<config>/<tfm>/<exe>).
- Verify il2CppFolder resolves to the correct source root containing the tool project.
- If not doing dev builds, unset the dev-override env/setting so the deploy location is used instead.
Example fix
/* no source edit; environment fix */ // before: IL2CPP dev folder points at un-built checkout // after: build il2cpp toolchain first // bee il2cpp::il2cpp // then retry the editor build
Defensive patterns
Strategy: validation
Validate before calling
var binDir = Path.Combine(il2CppFolder, toolName, "bin");
if (!Directory.Exists(binDir) || !Directory.EnumerateFiles(binDir, "*" + expectedToolExecutableName, SearchOption.AllDirectories).Any())
throw new InvalidOperationException($"Build the {toolName} toolchain in {il2CppFolder} first."); Try / catch
try { var exe = ResolveToolExecutable(...); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not appear to be built"))
{ ReportDevBuildMissing(ex); throw; } Prevention
- Run the bee build for the IL2CPP toolchain before launching the editor from a dev enlistment.
- Keep the dev IL2CPP folder override unset when not doing dev builds.
When it happens
Trigger: Running from a dev IL2CPP location (isDevelopmentLocation == true) where toolName/bin does not exist or contains no file matching *<expectedToolExecutableName>; the tool project has not been compiled, or the checkout is incomplete.
Common situations: Building the editor from a source enlistment where the IL2CPP submodule hasn't been built; pointing the dev override at a stale or partial clone; renaming/moving the tool project so the bin output path changed.
Related errors
- Could not determine which of the {candidates.Length} of {too
- {name} does not appear to be built in {il2CppFolder}
- Could not map typename 'GameManager' to type info (initializ
- ApiCompatibilityLevel.{0} is not supported!
- Unhandled scripting backend {scriptingBackend}
AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13).
Data as JSON: /api/errors/bc2d7050f094e024.
Report an issue: GitHub.