xai-org/grok-build · critical

{what} '{value}' must not start with '-'

Error message

{what} '{value}' must not start with '-'

What it means

ensure_ref_arg_safe rejects any ref value beginning with '-' because git would parse such an argument as an option/flag rather than a ref name (argument injection). The library throws this to prevent client-influenced refs from being smuggled into the git command line as flags; call sites additionally pass --end-of-options as defense in depth.

Source

Thrown at crates/codegen/xai-grok-workspace/src/session/git.rs:3085

    if merge_in_progress(git_root).await? {
        let files = git_cli(git_root, &["diff", "--name-only", "--diff-filter=U"])
            .await?
            .lines()
            .map(str::to_owned)
            .collect();
        return Ok(GitSyncBaseResult {
            outcome: GitSyncBaseOutcome::Conflicts { files },
        });
    }
    anyhow::bail!("merge of base ref '{base}' failed: {merge_out}")
}
/// Reject a ref/branch value that could be parsed as a git option (leading `-`)
/// or that carries whitespace/control characters or `..`. A boundary guard for
/// client-influenced refs (notably `base_ref`) so they cannot be smuggled in as
/// flags; combined with `--end-of-options` at each call site.
fn ensure_ref_arg_safe(value: &str, what: &str) -> Result<()> {
    anyhow::ensure!(!value.is_empty(), "{what} must not be empty");
    anyhow::ensure!(
        !value.starts_with('-'),
        "{what} '{value}' must not start with '-'"
    );
    anyhow::ensure!(
        !value.chars().any(|c| c.is_whitespace() || c.is_control()),
        "{what} '{value}' contains whitespace or control characters"
    );
    anyhow::ensure!(
        !value.contains(".."),
        "{what} '{value}' must not contain '..'"
    );
    Ok(())
}
/// Seed a committed `.gitignore` (secrets never enter git)
/// when a fresh conversation branch is created and the repo has none. Distinct
/// from [`seed_default_excludes`], which seeds the *local-only* `info/exclude`
/// as a `stage_all` backstop; this file is meant to be committed, so it also
/// protects explicit user commits and BYO-remote exports. Never overwrites an

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Remove the leading '-' — use a valid ref name (letters, digits, '/', '_', '-', '.', not starting with '-') .
  2. Sanitize or reject client input at the API boundary with the same rule the library uses (starts_with('-')).
  3. If you control both sides and truly need an odd name, rename the ref to something that does not collide with option syntax.

Example fix

// before
let branch = user_input.trim().to_string();
git_ops.merge_to_main(&root, &branch, "main", false).await?;
// after
let branch = user_input.trim().to_string();
anyhow::ensure!(!branch.starts_with('-'), "invalid branch name");
git_ops.merge_to_main(&root, &branch, "main", false).await?;
Defensive patterns

Strategy: validation

Validate before calling

if ref_name.starts_with('-') { return Err(format!("ref '{}' may not start with '-'", ref_name)); }

Try / catch

// treat as client input error, not retryable
match result {
    Err(e) if e.to_string().contains("must not start with '-'") => return Err(HttpError::bad_request(e.to_string())),
    other => other,
}

Prevention

When it happens

Trigger: Passing a caller-supplied ref/branch string starting with '-' (e.g. "--upload-pack=evil", "-o", "-C/tmp") into any git operation that validates it via ensure_ref_arg_safe in crates/codegen/xai-grok-workspace/src/session/git.rs:3085.

Common situations: A malicious or buggy client sends a branch name like "--exec=cmd"; an upstream system echoes back a git output line that includes a flag; test fixtures accidentally use "-test-branch" as a name.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/45caf72dfa878e62. Report an issue: GitHub.