zeroclaw-labs/zeroclaw · error · anyhow::Error

Branch name contains invalid characters

Error message

Branch name contains invalid characters

What it means

After the single-token shape check passes, git checkout rejects branch names containing '@', '^', or '~' with 'Branch name contains invalid characters'. These characters are the carriers of git revision syntax: '@{' addresses refs like stash@{0} and HEAD@{1}, while '~' and '^' express ancestor ranges like HEAD~2 or main^2. Accepting them would let the 'checkout a branch' operation silently perform reflog jumps or detached-revision checkouts, so the tool restricts checkout to plain branch names. This is a policy restriction of the tool, not a git limitation — the CLI itself accepts those revisions.

Source

Thrown at crates/zeroclaw-tools/src/git_operations.rs:600

                    .with_outcome(::zeroclaw_log::EventOutcome::Failure)
                    .with_attrs(::serde_json::json!({"param": "branch"})),
                "git_operations: missing branch parameter"
            );
            anyhow::Error::msg("Missing 'branch' parameter")
        })?;

        // Sanitize branch name
        let sanitized = self.sanitize_git_args(branch)?;

        if sanitized.is_empty() || sanitized.len() > 1 {
            anyhow::bail!("Invalid branch specification");
        }

        let branch_name = &sanitized[0];

        // Block dangerous branch names
        if branch_name.contains('@') || branch_name.contains('^') || branch_name.contains('~') {
            anyhow::bail!("Branch name contains invalid characters");
        }

        let output = self
            .run_git_command(&["checkout", branch_name], working_dir)
            .await;

        match output {
            Ok(_) => Ok(ToolResult {
                success: true,
                output: format!("Switched to branch: {branch_name}").into(),
                error: None,
            }),
            Err(e) => Ok(ToolResult {
                success: false,
                output: ToolOutput::default(),
                error: Some(format!("Checkout failed: {e}")),
            }),
        }

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Pass a plain branch name that exists locally, e.g. {"branch": "main"} or {"branch": "feature-x"}.
  2. For detached-HEAD/history navigation, create or check out a branch at the target revision using the CLI or another tool surface — this tool intentionally will not take HEAD~1.
  3. If your branch genuinely contains '@', rename it (git branch -m) to a dash-separated name before using this checkout tool.
  4. Use git_branch-style operations to list valid branch names first and pick from those.

Example fix

// before
let args = serde_json::json!({ "branch": "HEAD~1" }); // revision syntax, not a branch name
// tool bails: Branch name contains invalid characters

// after
let args = serde_json::json!({ "branch": "main" });
Defensive patterns

Strategy: type-guard

Validate before calling

fn build_checkout_args(branch: &str) -> Option<serde_json::Value> {
    is_plain_branch_name(branch).then(|| serde_json::json!({ "branch": branch }))
}

Type guard

fn is_plain_branch_name(branch: &str) -> bool {
    !branch.contains('@') && !branch.contains('^') && !branch.contains('~')
}

Try / catch

match tool_result {
    Err(e) if e.to_string().contains("Branch name contains invalid characters") => {
        // revision syntax was passed; resolve it to a concrete branch name first
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling checkout with {"branch": "HEAD~1"}, {"branch": "main^"}, or {"branch": "stash@{0}"}. Also any legitimately created branch whose name contains '@' (git allows branch names with '@' as long as they are not exactly '@').

Common situations: An agent tries to navigate history and reuses revision syntax in the branch field; a caller wants to check out a stashed state via stash@{0}; a branch was created with an email-like name (user@feature) and now cannot be checked out through this tool; porting a shell script that used HEAD~1 directly.

Understand the failure class

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/550c1439d363a2ac. Report an issue: GitHub.