github/copilot-sdk · error · InvalidOperationException

Could not determine directory for

Error message

Could not determine directory for '{cliPath}'.

What it means

ResolveRuntimePathForExplicitCli computes the directory of an explicitly configured CLI entrypoint path to search for the runtime library next to it. Path.GetDirectoryName returned null after Path.GetFullPath (e.g. a path rooted to a filesystem root with no directory component), so the client cannot proceed and throws.

Solutions

  1. Set the explicit CLI path to a full path of the actual CLI file (not a root or directory), e.g. /usr/local/bin/copilot.
  2. Guard the configured value before assigning it: check File.Exists and that it has a parent directory.
  3. If the value comes from an env var or CLI flag, validate/trim it and fail fast with a clear message when it is not a file path.
  4. Alternatively place the runtime library in the CLI's directory (flat layout) so resolution succeeds once the path is correct.

Example fix

// before
options.CliPath = Environment.GetEnvironmentVariable("COPILOT_CLI") ?? "/";

// after
var cli = Environment.GetEnvironmentVariable("COPILOT_CLI");
options.CliPath = cli is { Length: > 0 } && File.Exists(cli)
    ? Path.GetFullPath(cli)
    : throw new InvalidOperationException($"COPILOT_CLI must be a valid CLI file path, got '{cli}'");
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(cliPath) ||
    !File.Exists(cliPath) ||
    Path.GetDirectoryName(Path.GetFullPath(cliPath)) is null)
    throw new ArgumentException($"CliPath must be a valid file path, got '{cliPath}'");

Type guard

static bool IsValidCliPath(string? p) =>
    p is { Length: > 0 } && File.Exists(p) &&
    Path.GetDirectoryName(Path.GetFullPath(p)) is { Length: > 0 };

Try / catch

try
{
    await client.StartAsync();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Could not determine directory"))
{
    logger.LogError(ex, "Configured CliPath has no resolvable directory");
}

Prevention

When it happens

Trigger: Path.GetDirectoryName(Path.GetFullPath(cliPath)) returns null at Client.cs:2557 when the explicit CLI path resolves to a bare root (e.g. "/" or "C:\") or another form with no directory portion.

Common situations: Setting the CLI path option to a root path, an empty-ish path that normalizes to a root, or a malformed path; passing an environment variable or argument that was meant to name the CLI directory rather than a file; misconfigured container/image where the expected CLI file is missing and a fallback root path is used.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/d2b24ae41fe36f60. Report an issue: GitHub.

Appendix: source

Thrown at dotnet/src/Client.cs:2557

        }
        else if (OperatingSystem.IsMacOS()) os = "osx";
        else return null;

        var arch = System.Runtime.InteropServices.RuntimeInformation.OSArchitecture switch
        {
            System.Runtime.InteropServices.Architecture.X64 => "x64",
            System.Runtime.InteropServices.Architecture.Arm64 => "arm64",
            _ => null,
        };

        return arch != null ? $"{os}-{arch}" : null;
    }

    private static string ResolveRuntimePathForExplicitCli(string cliPath)
    {
        var fullEntrypoint = Path.GetFullPath(cliPath);
        var directory = Path.GetDirectoryName(fullEntrypoint)
            ?? throw new InvalidOperationException($"Could not determine directory for '{cliPath}'.");
        var flatLibraryPath = Path.GetFullPath(
            $"{directory}{Path.DirectorySeparatorChar}{FfiRuntimeHost.GetRuntimeLibraryFileName()}");
        if (File.Exists(flatLibraryPath))
        {
            return flatLibraryPath;
        }
        var adjacentPrebuildPath = Path.Combine(directory, "runtime.node");
        if (File.Exists(adjacentPrebuildPath))
        {
            return adjacentPrebuildPath;
        }
        var prebuildsLibraryPath = Path.Combine(
            directory, "prebuilds", GetNapiPrebuildsFolderOrThrow(), "runtime.node");
        return File.Exists(prebuildsLibraryPath)
            ? prebuildsLibraryPath
            : throw new InvalidOperationException(
                $"FFI runtime library not found. Looked for '{flatLibraryPath}', '{adjacentPrebuildPath}', and '{prebuildsLibraryPath}'.");
    }

View on GitHub (pinned to cd8cf15dc3)