can1357/oh-my-pi · error · Error
Security scans require a Git repository: ${request.cwd}
Error message
Security scans require a Git repository: ${request.cwd} What it means
buildPlanMaterial resolves the Git repository root for a security scan plan via the git adapter. If `adapter.root()` returns null (the resolved path is not inside a Git work tree), the function throws to refuse planning a scan outside version control. Security scans are anchored to a repo root so findings are repository-relative and reproducible.
Source
Thrown at packages/coding-agent/src/security/preflight.ts:320
}
interface SecurityPlanMaterial {
repositoryRoot: string;
target: SecurityTarget;
knowledgeBases: SecurityKnowledgeBaseRef[];
output: SecurityOutputPlan;
model: SecurityModelRef;
account: SecurityAccountRef;
configFingerprint: string;
workflowFingerprint: string;
}
async function buildPlanMaterial(
request: SecurityPlanRequest,
adapter: SecurityGitAdapter,
): Promise<SecurityPlanMaterial> {
const repositoryRoot = await adapter.root(path.resolve(request.cwd), request.signal);
if (!repositoryRoot) throw new Error(`Security scans require a Git repository: ${request.cwd}`);
const canonicalRoot = await fs.realpath(repositoryRoot);
const target = await normalizeTarget(canonicalRoot, request.target, adapter, request.signal);
const knowledgeBases = await normalizeKnowledgeBases(request.knowledgeBasePaths, canonicalRoot);
const output = await normalizeOutput(canonicalRoot, request.outputRoot, request.archiveExisting ?? false);
const model: SecurityModelRef = {
provider: request.model.provider,
modelId: request.model.modelId,
};
if (request.model.thinkingLevel !== undefined) model.thinkingLevel = request.model.thinkingLevel;
const account: SecurityAccountRef = {
provider: request.account.provider,
credentialId: request.account.credentialId,
};
if (request.account.accountId !== undefined) account.accountId = request.account.accountId;
if (request.account.email !== undefined) account.email = request.account.email;
if (request.account.organizationId !== undefined) account.organizationId = request.account.organizationId;
if (request.account.organizationName !== undefined) account.organizationName = request.account.organizationName;
return {View on GitHub (pinned to 9690622007)
Solutions
- Run `git init` (and an initial commit) in request.cwd or a parent directory so a work-tree root resolves
- Pass a cwd that is inside an existing Git repository
- Verify with `git -C <cwd> rev-parse --show-toplevel` that the root resolves before invoking the scan
- If .git was lost during copy/extract, restore it or re-clone the project
Example fix
// before
await material({ cwd: "/tmp/snapshot", ... });
// after
const $ = Bun.$; await $`git -C /tmp/snapshot rev-parse --show-toplevel`; // ensure repo first
await material({ cwd: "/home/me/project", ... }); Defensive patterns
Strategy: validation
Validate before calling
const root = await $`git -C ${cwd} rev-parse --show-toplevel`.nothrow();
if (root.exitCode !== 0) throw new Error(`cwd is not a git repo: ${cwd}`); Type guard
null
Try / catch
try { await material(request); } catch (e) { if (String(e.message).includes("require a Git repository")) { /* git init or fix cwd */ } else throw e; } Prevention
- Preflight with git rev-parse before scans
- Never scan snapshots without .git
When it happens
Trigger: Calling material()/buildPlanMaterial() with a request.cwd that is outside any Git repository, inside a bare repo where root() cannot resolve a work tree, or in a directory whose .git was removed/corrupted.
Common situations: Running security scans on a downloaded source snapshot or extracted tarball, pointing the scan at a temp directory, initializing a project without `git init`, or .git being excluded when copying a project.
Related errors
- not a repository: {path}
- Managed skill "${name}" SKILL.md is not a regular file; refu
- Shared-folder destination escapes its configured root
- Cannot resolve revision: ${options.revision}
- Path is not a file: ${pathArg}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/04255e3497f74983.
Report an issue: GitHub.