can1357/oh-my-pi · error · Error
Security knowledge base is not a file: ${input}
Error message
Security knowledge base is not a file: ${input} What it means
normalizeKnowledgeBases validates each configured security knowledge base path before a security preflight scan. Each input is resolved against baseDirectory, canonicalized with fs.realpath, and stat-ed; if the resulting entry is not a regular file (directory, symlink to dir, socket, etc.), the function refuses to proceed. This guarantees every knowledge base is a single hashable file whose sha256 and size can be pinned in the SecurityKnowledgeBaseRef.
Source
Thrown at packages/coding-agent/src/security/preflight.ts:235
repositoryRoot,
displayName,
includePaths,
excludePaths,
treeDigest: await digestWorkingTree(repositoryRoot, includePaths, excludePaths, adapter, signal),
};
if (revision !== null) target.revision = revision;
return target;
}
async function normalizeKnowledgeBases(
paths: readonly string[] | undefined,
baseDirectory: string,
): Promise<SecurityKnowledgeBaseRef[]> {
const results: SecurityKnowledgeBaseRef[] = [];
for (const input of paths ?? []) {
const canonical = await fs.realpath(path.resolve(baseDirectory, input));
const stats = await fs.stat(canonical);
if (!stats.isFile()) throw new Error(`Security knowledge base is not a file: ${input}`);
const digest = await hashFile(canonical);
results.push({ path: canonical, sha256: digest.sha256, size: digest.size });
}
return results.sort((left, right) => left.path.localeCompare(right.path));
}
async function normalizeOutput(
repositoryRoot: string,
outputRoot: string,
archiveExisting: boolean,
): Promise<SecurityOutputPlan> {
const requested = path.resolve(outputRoot);
const parent = await fs.realpath(path.dirname(requested));
const canonicalCandidate = path.join(parent, path.basename(requested));
if (pathIsWithin(canonicalCandidate, repositoryRoot)) {
throw new Error("Security output directory must be outside the scanned repository");
}
let existingState: SecurityOutputPlan["existingState"] = "absent";View on GitHub (pinned to 9690622007)
Solutions
- Point the knowledge base entry at the specific file (e.g. ./kb/rules.md), not its parent directory.
- Run `ls -l` on the path to confirm it is a regular file, not a directory or special file.
- If you intended multiple files, list each file as a separate entry in paths.
Example fix
// before
{ "knowledgeBases": ["./security/kb"] }
// after
{ "knowledgeBases": ["./security/kb/rules.md", "./security/kb/policy.md"] } Defensive patterns
Strategy: validation
Validate before calling
import * as fs from "node:fs/promises";
import * as path from "node:path";
for (const kb of paths) {
const resolved = path.resolve(baseDirectory, kb);
const st = await fs.stat(resolved);
if (!st.isFile()) throw new Error(`Knowledge base must be a regular file: ${kb}`);
} Try / catch
try {
await knowledgeBases(baseDirectory, paths);
} catch (err) {
if ((err as Error).message.includes("is not a file")) {
// surface which path was wrong and stop configuration load
}
throw err;
} Prevention
- Always list individual files, never directories, in knowledge base config.
- Run `file <path>` or `ls -l` on each configured path before starting a scan.
- Keep knowledge base files in a dedicated directory so glob/directory mistakes are obvious.
When it happens
Trigger: Calling knowledgeBases()/normalizeKnowledgeBases with a `paths` entry that resolves to a directory (e.g. passing a folder like ./kb or ./kb/ instead of ./kb/rules.md), or to a non-regular file (FIFO, device, socket).
Common situations: Config points at a knowledge-base directory instead of the file inside it; trailing-slash path that auto-completes to a directory; a docs folder that used to contain a single file; symlink to a directory used as a shortcut.
Related errors
- Security output directory must be outside the scanned reposi
- Shared-folder destination escapes its configured root
- Security output path exists and is not a directory
- Security output directory does not have a canonical identity
- Security output directory is not empty; enable archiveExisti
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/149a7bc8b0e1f0e7.
Report an issue: GitHub.