gitbutlerapp/gitbutler · error · anyhow::Error

Invalid path scheme: {}

Error message

Invalid path scheme: {}

What it means

open_that (crates/but-api/src/open/mod.rs:41-59) only opens URLs whose scheme is in its allowlist: http, https, mailto, vscode, vscodium, vscode-insiders, zed, windsurf, cursor, trae, antigravity-ide, and file. Any other scheme bails immediately with this message before any opener command runs.

Source

Thrown at crates/but-api/src/open/mod.rs:58

/// be converted to a path, or every available opener command fails to launch.
pub(crate) fn open_that(target_url: &Url) -> anyhow::Result<()> {
    if ![
        "http",
        "https",
        "mailto",
        "vscode",
        "vscodium",
        "vscode-insiders",
        "zed",
        "windsurf",
        "cursor",
        "trae",
        "antigravity-ide",
        "file",
    ]
    .contains(&target_url.scheme())
    {
        bail!("Invalid path scheme: {}", target_url.scheme());
    }

    if open_editor_url_as_command_invocation_on_wsl(target_url) {
        return Ok(());
    }

    fn clean_env_vars<'a, 'b>(
        var_names: &'a [&'b str],
    ) -> impl Iterator<Item = (&'b str, String)> + 'a {
        var_names
            .iter()
            .filter_map(|name| env::var(name).map(|value| (*name, value)).ok())
            .map(|(name, value)| {
                (
                    name,
                    value
                        .split(':')
                        .filter(|path| {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Use a supported scheme: http/https/mailto/file or one of the listed editor schemes (vscode, cursor, zed, windsurf, ...)
  2. Open unsupported URLs with the OS opener directly instead of this API
  3. For a genuinely needed scheme, extend the allowlist in open_that and ship it, rather than working around at call sites

Example fix

// before
openThat(new URL('jetbrains://open?file=x.ts'));
// error: Invalid path scheme: jetbrains

// after
openThat(new URL('vscode://file/x.ts')); // allowed editor scheme
Defensive patterns

Strategy: type-guard

Type guard

const OPENABLE_SCHEMES = new Set([
  'http', 'https', 'mailto', 'file',
  'vscode', 'vscodium', 'vscode-insiders',
  'zed', 'windsurf', 'cursor', 'trae', 'antigravity-ide',
]);

function isOpenableScheme(url: URL): boolean {
  return OPENABLE_SCHEMES.has(url.protocol.replace(':', '').toLowerCase());
}

Try / catch

try {
  await openThat(url);
} catch (e) {
  if (String(e).startsWith('Invalid path scheme')) {
    // open with the OS shell opener directly instead
  } else throw e;
}

Prevention

When it happens

Trigger: Routing links like ssh://git@..., jetbrains://..., slack://..., or a typo'd scheme (htps://) through GitButler's open-URL API; a new editor scheme that has not been added to the allowlist.

Common situations: Apps embedding GitButler's opener for arbitrary clicked links; users on IDEs whose URL scheme (e.g. jetbrains://) is not in the list; scheme casing or whitespace quirks in constructed URLs.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/1501d8af820a67d1. Report an issue: GitHub.