{"record":{"id":"2755ee6f07d4420b","repo":"stablyai/orca","slug":"invalid-merge-request-iid-string-mriid","errorCode":null,"errorMessage":"Invalid merge request iid: ${String(mrIid)}","messagePattern":"Invalid merge request iid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/gitlab/mr-head-tracking-ref.ts","lineNumber":28,"sourceCode":"\ntype LocalGitExecOptions = {\n  cwd: string\n  wslDistro?: string\n}\n\n// Why: the relay's read-only git.exec channel rejects `fetch`, so SSH repos\n// must use the dedicated git.fetchGitLabMergeRequestHeadRef RPC. Mirrors\n// fetchGitHubPullRequestHeadRef so both providers pin the durable head ref\n// the same way.\nexport async function fetchGitLabMergeRequestHeadRef(\n  repo: { path: string; connectionId?: string | null },\n  sshGitProvider: SshGitProvider | null | undefined,\n  remote: string,\n  mrIid: number,\n  options: { localGitExecOptions?: LocalGitExecOptions } = {}\n): Promise<string> {\n  if (!isValidReviewHeadNumber(mrIid)) {\n    throw new Error(`Invalid merge request iid: ${String(mrIid)}`)\n  }\n  if (!isSafeReviewHeadFetchRemote(remote)) {\n    throw new Error('Merge request fetch remote must not start with \"-\".')\n  }\n  if (!repo.connectionId) {\n    const localGitExecOptions = options.localGitExecOptions ?? { cwd: repo.path }\n    const remoteComponent = await getReviewHeadRemoteComponent(remote, localGitExecOptions)\n    // Why: return the same path the fetch wrote so callers don't re-resolve identity.\n    const localRef = gitlabMergeRequestHeadLocalRef(remoteComponent, mrIid)\n    await gitExecFileAsync(\n      ['fetch', '--no-tags', remote, `+refs/merge-requests/${mrIid}/head:${localRef}`],\n      {\n        ...localGitExecOptions,\n        timeout: REVIEW_HEAD_FETCH_TIMEOUT_MS\n      }\n    )\n    return localRef\n  }","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/gitlab/mr-head-tracking-ref.ts#L10-L46","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait fetchGitLabMergeRequestHeadRef(repo, ssh, remote, Number(input.iid))\n// after\nconst mrIid = Number(input.iid)\nif (!Number.isInteger(mrIid) || mrIid <= 0) {\n  throw new Error(`Merge request iid must be a positive integer, got: ${input.iid}`)\n}\nawait fetchGitLabMergeRequestHeadRef(repo, ssh, remote, mrIid)","handlingStrategy":"validation","validationCode":"function isValidMrIid(value: unknown): value is number {\n  return typeof value === 'number' && Number.isInteger(value) && value > 0\n}","typeGuard":"function isValidReviewHeadNumber(value: unknown): value is number {\n  return typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value > 0\n}","tryCatchPattern":null,"preventionTips":["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)."],"tags":["gitlab","validation","input","merge-request"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}