stablyai/orca · error
Invalid merge request iid: ${String(mrIid)}
Error message
Invalid merge request iid: ${String(mrIid)} What it means
Thrown by fetchGitLabMergeRequestHeadRef when the merge request iid fails isValidReviewHeadNumber — i.e. it is not a positive finite integer in the accepted range. This is an input-contract guard that runs before any git/network operation, so it never reflects a GitLab state, only a bad caller value.
Source
Thrown at src/main/gitlab/mr-head-tracking-ref.ts:28
type LocalGitExecOptions = {
cwd: string
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
}View on GitHub (pinned to 1136503c6a)
Solutions
- Validate/coerce the iid to a positive integer before calling: `if (!Number.isInteger(mrIid) || mrIid <= 0) throw ...`.
- Extract the iid from a trusted source — the GitLab API `iid` field or the MR URL's last numeric segment.
- If the iid comes from user input, parse with `Number(...)` and reject NaN/non-integers upstream.
Example fix
// before
await fetchGitLabMergeRequestHeadRef(repo, ssh, remote, Number(input.iid))
// after
const mrIid = Number(input.iid)
if (!Number.isInteger(mrIid) || mrIid <= 0) {
throw new Error(`Merge request iid must be a positive integer, got: ${input.iid}`)
}
await fetchGitLabMergeRequestHeadRef(repo, ssh, remote, mrIid) Defensive patterns
Strategy: validation
Validate before calling
function isValidMrIid(value: unknown): value is number {
return typeof value === 'number' && Number.isInteger(value) && value > 0
} Type guard
function isValidReviewHeadNumber(value: unknown): value is number {
return typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value > 0
} Prevention
- Coerce and validate iid from trusted API fields or URL segments before passing.
- Never default an unset iid to 0; require an explicit positive integer.
- Unit-test the fetch path with boundary iid values (0, 1, floats, NaN).
When it happens
Trigger: Passing mrIid as 0, a negative number, NaN, Infinity, a float, or a value outside the valid review-head number range to fetchGitLabMergeRequestHeadRef. Typically a caller that derived the iid from untrusted UI input or an unvalidated API field without coercing/parsing.
Common situations: Parsing MR URLs where the iid segment is missing or non-numeric; off-by-one when iterating an empty list (iid defaults to 0); float arithmetic producing NaN; passing a full MR object instead of its iid number.
Related errors
- coordinate action requires a visible window and coordinates
- {name} must be a positive integer
- Hermes cron requires a prompt.
- Hermes cron requires a schedule.
- A Claude config directory path is required.
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/2755ee6f07d4420b.
Report an issue: GitHub.