{"record":{"id":"5118fb2061eda285","repo":"stablyai/orca","slug":"missing-head-sha","errorCode":null,"errorMessage":"missing head SHA","messagePattern":"missing head SHA","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/github/client.ts","lineNumber":3011,"sourceCode":"    { ...ghOptions, ...githubHostExecOptions(ownerRepo) }\n  )\n  const parsed = JSON.parse(stdout) as unknown\n  if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n    throw new Error('invalid response shape')\n  }\n  const restData = parsed as RestPullRequest\n  const mapped = mapRestPullRequest(restData)\n  if (\n    options.requireUsableStackMetadata &&\n    restData.stack !== undefined &&\n    restData.stack !== null\n  ) {\n    // Why: GitHub omits stack for ordinary PRs; only unusable non-null metadata is unsafe.\n    if (!isUsableRestStackMetadata(restData.stack) || !mapped.stack) {\n      throw new Error('malformed stack')\n    }\n    if (!isGitObjectId(restData.head?.sha)) {\n      throw new Error('missing head SHA')\n    }\n  }\n  return mapped\n}\n\nfunction prunePRStackSummaryCache(now = Date.now()): void {\n  for (const [key, cached] of prStackSummaryCache) {\n    if (cached.expiresAt <= now) {\n      prStackSummaryCache.delete(key)\n    }\n  }\n  while (prStackSummaryCache.size > PR_STACK_SUMMARY_CACHE_MAX_ENTRIES) {\n    const oldestKey = prStackSummaryCache.keys().next().value\n    if (oldestKey === undefined) {\n      return\n    }\n    prStackSummaryCache.delete(oldestKey)\n  }","sourceCodeStart":2993,"sourceCodeEnd":3029,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/github/client.ts#L2993-L3029","documentation":"Thrown by getRestPRByNumber after stack metadata passed validation but the PR's head SHA is not a valid git object ID (checked via isGitObjectId). Stack-aware code needs the head SHA to wire parent/child PR relationships to local refs, so a missing or malformed SHA makes the stack unusable even though the stack structure parsed.","triggerScenarios":"GitHub returned a PR whose head repo was deleted (head.sha null/empty); a draft PR from a deleted fork; an Enterprise Server bug returning an abbreviated or malformed SHA; the response was partially truncated.","commonSituations":"PR head branch deleted before the lookup; fork deleted by owner; SHA field present but not a 40-char hex object id.","solutions":["Check the PR on github.com — if the head branch/repo is gone, the lookup legitimately cannot provide a SHA.","If the PR looks healthy, dump the raw response and verify `head.sha` is a full 40-char hex string.","For a deleted-head PR, treat the stack view as unavailable rather than retrying."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function isValidObjectId(sha: unknown): sha is string {\n  return typeof sha === 'string' && /^[0-9a-f]{40}$/i.test(sha)\n}","typeGuard":"function isValidObjectId(sha: unknown): sha is string {\n  return typeof sha === 'string' && /^[0-9a-f]{40}$/i.test(sha)\n}","tryCatchPattern":"try {\n  const pr = await getRestPRByNumber(ownerRepo, number, ghOptions, { requireUsableStackMetadata: true })\n} catch (err) {\n  if ((err as Error).message === 'missing head SHA') {\n    showStackUnavailableDueToDeletedHead(number)\n    return null\n  }\n  throw err\n}","preventionTips":["Treat PRs with deleted head branches/forks as stack-unavailable rather than erroring.","Validate head.sha presence before enabling stack-aware UI for a PR.","Log the PR number when this fires to spot deleted-head patterns."],"tags":["github","api","stacked-prs","sha","validation"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}