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

  1. Validate/coerce the iid to a positive integer before calling: `if (!Number.isInteger(mrIid) || mrIid <= 0) throw ...`.
  2. Extract the iid from a trusted source — the GitLab API `iid` field or the MR URL's last numeric segment.
  3. 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

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


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/2755ee6f07d4420b. Report an issue: GitHub.