koala73/worldmonitor · error · Error
git is required to prove the merge commit reached the defaul
Error message
git is required to prove the merge commit reached the default branch
What it means
check-stacked-merge verifies that a merged PR's merge commit is actually reachable from the remote default branch (origin/<defaultBranch>). Proving ancestry requires running git; when the injected `git` dependency is not a function (dependency not provided/wired), the script throws rather than silently skipping the ancestry proof, which would let an unmerged-to-default merge pass.
Solutions
- Pass a working git executor function to checkStackedMerge (e.g. the script's own runGit helper)
- Fix the test/mock so `git` is a vi.fn/exec-style function, not undefined or a plain value
- Ensure the host environment has git installed if the executor shells out to it
- Confirm the option name matches the current function signature after any refactor
Example fix
// before
await checkStackedMerge({ pull });
// after
await checkStackedMerge({ pull, git: runGit }); Defensive patterns
Strategy: validation
Validate before calling
if (typeof git !== 'function') throw new Error('checkStackedMerge requires a git executor function');
await checkStackedMerge({ pull, git }); Type guard
const hasGitExecutor = (opts) => typeof opts.git === 'function';
Try / catch
try {
await checkStackedMerge({ pull, git });
} catch (e) {
if (e.message.includes('git is required')) {
console.error('Wire the git executor dependency into checkStackedMerge');
} else throw e;
} Prevention
- Always pass the git executor when calling checkStackedMerge
- Update test mocks whenever the dependency-injection signature changes
- Ensure git is installed where the script runs
- Type-check options objects (JSDoc/TS) so a missing git option fails early
When it happens
Trigger: Calling checkStackedMerge for an already-merged PR while the `git` option was omitted, passed as null/undefined, or set to a non-function (e.g. a wrong mock or a string command instead of an executor function).
Common situations: Test harness refactored the dependency injection and stopped passing the git executor; a caller imported the check in a new script and forgot the git option; environment without git binary combined with a lazy git wrapper that resolves to undefined.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- cannot resolve origin/main for the deploy-drift comparison;
- global fetch is unavailable — Node 18+ is required
- --args must be valid JSON: ${err.message}
- `get` needs an API path, e.g. `worldmonitor get /api/health`
- `call` needs a tool name, e.g. `worldmonitor call get_countr
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/32180cae9d637f41.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/check-stacked-merge.mjs:300
}
baseHeadPulls = listPullsByHead({ gh, repository, owner, headRef: baseRef });
}
const verdict = evaluatePreMergeGuard({ defaultBranch, baseRef, baseHeadPulls });
if (verdict.ok) {
return { ...verdict, exitCode: 0 };
}
return {
...verdict,
exitCode: 1,
annotation: preMergeAnnotation(verdict, baseRef),
};
}
const mergeSha = pull.merge_commit_sha;
const merged = isMergedPull(pull);
if (!merged) return { ok: true, reason: 'not-merged', exitCode: 0 };
if (typeof git !== 'function') {
throw new Error('git is required to prove the merge commit reached the default branch');
}
const ref = `origin/${defaultBranch}`;
const isAncestor = merged && typeof mergeSha === 'string' && mergeSha.length > 0
? confirmAncestry({
git,
commit: mergeSha,
ref,
defaultBranch,
shouldRetry: baseRef === defaultBranch,
sleep,
})
: false;
const { parents = [], pendingParent } = !isAncestor && mergeSha && typeof gh === 'function'
? findPendingParent({ gh, git, repository, defaultBranch, pull, mergeSha })
: {};
const verdict = evaluatePostMergeAncestry({ merged, mergeSha, isAncestor, pendingParent });
const alarm = formatOrphanIssue({View on GitHub (pinned to 7d06c8633d)