dotnet/runtime · error · RuntimeError

Tool not found. Have you built the runtime repo and created…

Error message

Tool {tool_name} not found. Have you built the runtime repo and created a Core_Root, or put it on your PATH?

What it means

Raised by find_tool after exhausting all search locations (Core_Root, product build directory, PATH) for a required tool binary such as superpmi, mcs, clrjit, or dotnet. The message guides the developer to build the runtime repo and create a Core_Root or place the tool on PATH. This is the most common startup failure for SuperPMI workflows.

Solutions

  1. Build the runtime: run the repo build script (build.cmd/build.sh) for coreclr and create a Core_Root; then re-run superpmi.py.
  2. If the tool is from jitutils (superpmi, mcs), build https://github.com/dotnet/jitutils and add its bin directory to PATH.
  3. Pass --core_root <path> and/or --product_location <path> explicitly to point at your built output.
  4. Confirm the tool filename matches your OS (e.g. superpmi.exe on Windows vs superpmi on Linux) and your build_type/arch.

Example fix

// before
if throw_on_not_found:
    raise RuntimeError("Tool " + tool_name + " not found. Have you built the runtime repo and created a Core_Root, or put it on your PATH?")
// after (fix invocation, not code)
# Build runtime and create Core_Root, then:
python superpmi.py <mode> --core_root <path-to-Core_Root>
# Or install jitutils and add to PATH:
#   build jitutils, then `export PATH=$PATH:<jitutils>/bin`
Defensive patterns

Strategy: validation

Validate before calling

import os
def preflight_tool(coreclr_args, tool_name):
    locations = []
    if hasattr(coreclr_args, 'core_root') and coreclr_args.core_root:
        locations.append(os.path.join(coreclr_args.core_root, tool_name))
    if hasattr(coreclr_args, 'product_location') and coreclr_args.product_location:
        locations.append(os.path.join(coreclr_args.product_location, tool_name))
    found = [p for p in locations if os.path.isfile(p)]
    if not found:
        raise RuntimeError(f"{tool_name} not found in Core_Root or product_location. Build the runtime (and jitutils for superpmi/mcs), then pass --core_root or add the bin dir to PATH.")
    return found[0]

Try / catch

try:
    tool_path = find_tool(coreclr_args, tool_name)
except RuntimeError as e:
    logging.error(str(e))
    logging.error('Build steps: runtime -> Core_Root; jitutils -> add bin to PATH')
    raise

Prevention

When it happens

Trigger: find_tool(coreclr_args, tool_name, ...) is called for tools like superpmi/superpmi.exe, mcs/mcs.exe, clrjit.dll, or dotnet; none of Core_Root, product_location, or PATH contain the file, and throw_on_not_found is True (default). Common when the runtime has not been built, when Core_Root was not created, or when jitutils tools are not on PATH.

Common situations: First run on a fresh clone without building; building only part of the product so Core_Root is incomplete; forgetting to build jitutils and add its bin to PATH; mismatched build_type/arch so the expected tool name isn't where expected.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/1a0f2b4a47e408b1. Report an issue: GitHub.

Appendix: source

Thrown at src/coreclr/scripts/superpmi.py:3882

    # Next, look in the built product directory, if it exists. We can use superpmi/mcs directly from the
    # product build directory instead from Core_Root because they don't depend on managed code libraries.
    if search_product_location and hasattr(coreclr_args, "product_location") and coreclr_args.product_location is not None and os.path.isdir(coreclr_args.product_location):
        tool_path = os.path.join(coreclr_args.product_location, tool_name)
        if os.path.isfile(tool_path):
            logging.debug("Using %s from product build location: %s", tool_name, tool_path)
            return tool_path

    # Finally, look on the PATH
    if search_path:
        path_var = os.environ.get("PATH")
        if path_var is not None:
            tool_path = find_file(tool_name, path_var.split(os.pathsep))
            if tool_path is not None:
                logging.debug("Using %s from PATH: %s", tool_name, tool_path)
                return tool_path

    if throw_on_not_found:
        raise RuntimeError("Tool " + tool_name + " not found. Have you built the runtime repo and created a Core_Root, or put it on your PATH?")

    return None


def determine_superpmi_tool_name(coreclr_args):
    """ Determine the superpmi tool name based on the OS

    Args:
        coreclr_args (CoreclrArguments): parsed args

    Return:
        (str) Name of the superpmi tool to use
    """

    if coreclr_args.host_os == "osx" or coreclr_args.host_os == "linux":
        return "superpmi"
    elif coreclr_args.host_os == "windows":
        return "superpmi.exe"

View on GitHub (pinned to 60108ba66e)