stablyai/orca · error
Merge request fetch remote must not start with "-".
Error message
Merge request fetch remote must not start with "-".
What it means
Thrown by fetchGitLabMergeRequestHeadRef when isSafeReviewHeadFetchRemote(remote) is false — the remote name begins with '-', which git would interpret as a flag rather than a refspec argument (argument-injection guard). This protects the downstream `git fetch --no-tags <remote> ...` from a maliciously or accidentally malformed remote name.
Source
Thrown at src/main/gitlab/mr-head-tracking-ref.ts:31
wslDistro?: string
}
// Why: the relay's read-only git.exec channel rejects `fetch`, so SSH repos
// must use the dedicated git.fetchGitLabMergeRequestHeadRef RPC. Mirrors
// fetchGitHubPullRequestHeadRef so both providers pin the durable head ref
// the same way.
export async function fetchGitLabMergeRequestHeadRef(
repo: { path: string; connectionId?: string | null },
sshGitProvider: SshGitProvider | null | undefined,
remote: string,
mrIid: number,
options: { localGitExecOptions?: LocalGitExecOptions } = {}
): Promise<string> {
if (!isValidReviewHeadNumber(mrIid)) {
throw new Error(`Invalid merge request iid: ${String(mrIid)}`)
}
if (!isSafeReviewHeadFetchRemote(remote)) {
throw new Error('Merge request fetch remote must not start with "-".')
}
if (!repo.connectionId) {
const localGitExecOptions = options.localGitExecOptions ?? { cwd: repo.path }
const remoteComponent = await getReviewHeadRemoteComponent(remote, localGitExecOptions)
// Why: return the same path the fetch wrote so callers don't re-resolve identity.
const localRef = gitlabMergeRequestHeadLocalRef(remoteComponent, mrIid)
await gitExecFileAsync(
['fetch', '--no-tags', remote, `+refs/merge-requests/${mrIid}/head:${localRef}`],
{
...localGitExecOptions,
timeout: REVIEW_HEAD_FETCH_TIMEOUT_MS
}
)
return localRef
}
if (!sshGitProvider) {
throw new Error('SSH Git provider is not available. Reconnect to this target and try again.')
}View on GitHub (pinned to 1136503c6a)
Solutions
- Ensure the remote name is one of the actual remotes from `git remote` before calling.
- Reject remote names starting with '-' at the input boundary (UI/config parser).
- If the remote comes from stored state, validate it against the live `git remote` list on load.
Example fix
// before
await fetchGitLabMergeRequestHeadRef(repo, ssh, userInputRemote, mrIid)
// after
const safeRemote = /^[A-Za-z0-9][\w.-]*$/.test(userInputRemote) ? userInputRemote : null
if (!safeRemote) throw new Error(`Refusing unsafe remote name: ${userInputRemote}`)
await fetchGitLabMergeRequestHeadRef(repo, ssh, safeRemote, mrIid) Defensive patterns
Strategy: validation
Validate before calling
function isSafeRemoteName(remote: string): boolean {
return typeof remote === 'string' && remote.length > 0 && !remote.startsWith('-')
} Type guard
function isSafeReviewHeadFetchRemote(remote: unknown): remote is string {
return typeof remote === 'string' && remote.length > 0 && !remote.startsWith('-')
} Prevention
- Source remote names only from `git remote` output, never from raw user/config input.
- Reject any remote name starting with '-' at the input boundary.
- Treat the remote as untrusted data; validate before interpolating into git args.
When it happens
Trigger: Passing a remote value that starts with '-' (e.g. '--upload-pack=...', '-o', or any dash-prefixed string) to fetchGitLabMergeRequestHeadRef. Can occur if remote is sourced from untrusted config, a URL query param, or a corrupted stored workspace state.
Common situations: Remote name read from an untrusted/configurable source without sanitization; a bug where an empty remote is replaced by a default flag string; test fixtures passing flag-like strings.
Related errors
- Repo has no configured git remotes.
- Remote "${remote}" is not configured.
- Access denied: invalid submodule path
- Pull request fetch remote must not start with "-".
- ${name} must be a positive integer, received ${value}
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/ba77e04ed14dcd81.
Report an issue: GitHub.