{"record":{"id":"86ab5348f7f21f8e","repo":"mastra-ai/mastra","slug":"gh-missing","errorCode":"gh-missing","errorMessage":"The GitHub CLI (gh) is not installed in the sandbox. The sandbox template must include gh to open pull requests.","messagePattern":"The GitHub CLI \\(gh\\) is not installed in the sandbox\\. The sandbox template must include gh to open pull requests\\.","errorType":"exception","errorClass":"MaterializeError","httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/integrations/github/sandbox.ts","lineNumber":894,"sourceCode":"  title: string;\n  /** PR body (optional). */\n  body?: string;\n}\n\nexport interface CreatePullRequestResult {\n  /** The PR URL parsed from `gh pr create` stdout. */\n  url: string;\n}\n\n/**\n * Preflight that `gh` is installed in the sandbox. Only called on the PR path so\n * a missing `gh` never blocks clone/open. Surfaces an actionable error naming\n * the sandbox template requirement.\n */\nasync function assertGhAvailable(sandbox: ExecutableSandbox): Promise<void> {\n  const version = await sh(sandbox, 'gh --version');\n  if (version.exitCode !== 0) {\n    throw new MaterializeError(\n      'The GitHub CLI (gh) is not installed in the sandbox. The sandbox template must include gh to open pull requests.',\n      'gh-missing',\n    );\n  }\n}\n\n/** Match the first GitHub PR URL in `gh pr create` output. */\nfunction parsePullRequestUrl(stdout: string): string | undefined {\n  const match = stdout.match(/https:\\/\\/github\\.com\\/[^\\s]+\\/pull\\/\\d+/);\n  return match?.[0];\n}\n\n/**\n * Open a pull request from inside the sandbox via `gh pr create`. The token is\n * passed only through a per-invocation `GH_TOKEN` env scoped to the single `gh`\n * process (never persisted), all arguments are shell-quoted, and the resulting\n * PR URL is parsed from stdout.\n *","sourceCodeStart":876,"sourceCodeEnd":912,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/integrations/github/sandbox.ts#L876-L912","documentation":"assertGhAvailable runs `gh --version` before any PR creation; a non-zero exit throws MaterializeError('gh-missing'). The library checks explicitly so a missing GitHub CLI produces an actionable message naming the sandbox template requirement, rather than a confusing failure later in `gh pr create`.","triggerScenarios":"Calling createPullRequest against a sandbox whose image does not include the `gh` binary, or where gh exists but fails to execute (broken install, incompatible arch).","commonSituations":"Custom/minimal sandbox templates without gh; older sandbox images predating the gh requirement; PATH not including /usr/local/bin in the exec environment.","solutions":["Add gh to the sandbox template image (apt/brew install gh or official image)","Verify with `gh --version` inside the sandbox before opening PRs","Check PATH in the sandbox exec environment includes gh's install location","Use a newer version of the sandbox template that bundles gh"],"exampleFix":"// before (sandbox template)\nFROM ubuntu:22.04  # no gh\n// after\nFROM ubuntu:22.04\nRUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \\\n  && apt-get update && apt-get install -y gh","handlingStrategy":"validation","validationCode":"const v = await sh(sandbox, 'gh --version');\nif (v.exitCode !== 0) throw new Error('sandbox template must include gh before opening PRs');","typeGuard":null,"tryCatchPattern":"try {\n  await createPullRequest(sandbox, workdir, args);\n} catch (e) {\n  if (e instanceof MaterializeError && e.code === 'gh-missing') {\n    throw new Error('Rebuild sandbox template with gh installed; cannot open PR.');\n  }\n  throw e;\n}","preventionTips":["Include gh in the sandbox template (apt/brew or official image)","Add a template smoke test that runs `gh --version`","Pin the template so gh is never dropped by base-image changes"],"tags":["github-cli","sandbox","prerequisites"],"backgroundTag":"gh-cli-not-installed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}