can1357/oh-my-pi · error · Error
Invalid security plan id: ${planId}
Error message
Invalid security plan id: ${planId} What it means
SecurityStore.#planPath enforces that plan ids match /^secplan_[a-zA-Z0-9]+$/ before using them in the plans/<id>.json path. This rejects malformed ids and prevents traversal out of the store's plans directory.
Source
Thrown at packages/coding-agent/src/security/store.ts:195
get repositoryRoot(): string {
return this.#repositoryRoot;
}
get projectKey(): string {
return this.#projectKey;
}
get projectDirectory(): string {
return this.#projectDirectory;
}
#scanDirectory(scanId: string): string {
if (!/^secscan_[a-zA-Z0-9]+$/.test(scanId)) throw new Error(`Invalid security scan id: ${scanId}`);
return path.join(this.#projectDirectory, "scans", scanId);
}
#planPath(planId: string): string {
if (!/^secplan_[a-zA-Z0-9]+$/.test(planId)) throw new Error(`Invalid security plan id: ${planId}`);
return path.join(this.#projectDirectory, "plans", `${planId}.json`);
}
#indexPath(): string {
return path.join(this.#projectDirectory, "index.json");
}
async #ensureIndex(): Promise<void> {
try {
await this.#readIndex();
} catch (error) {
if (!isEnoent(error)) throw error;
await this.#writeIndex({
schemaVersion: STORE_SCHEMA_VERSION,
projectKey: this.#projectKey,
repositoryRoot: this.#repositoryRoot,
scanIds: [],
planIds: [],View on GitHub (pinned to 9690622007)
Solutions
- Use the plan id generated by putPlan (secplan_ prefixed) rather than a custom one
- Check you are not passing a scan id (secscan_...) to getPlan
- Sanitize/validate the id with /^secplan_[a-zA-Z0-9]+$/ before calling the store
- Recreate the plan if the original id is lost
Example fix
// before
store.getPlan("plan-001");
// after
const { planId } = await store.putPlan(plan); // "secplan_x9y8..."
store.getPlan(planId); Defensive patterns
Strategy: validation
Validate before calling
if (!/^secplan_[a-zA-Z0-9]+$/.test(planId)) throw new Error("bad plan id"); Type guard
function isPlanId(v: unknown): v is string { return typeof v === "string" && /^secplan_[a-zA-Z0-9]+$/.test(v); } Try / catch
try { store.getPlan(planId); } catch (e) { if (String(e.message).startsWith("Invalid security plan id")) { /* re-fetch id */ } else throw e; } Prevention
- Don't confuse secplan_ and secscan_ ids
- Validate format before store calls
When it happens
Trigger: putPlan/getPlan called with an id missing the 'secplan_' prefix or containing illegal characters (slashes, dots, hyphens, whitespace), usually an id produced outside the store.
Common situations: Hand-rolled plan ids like 'plan-001', ids remembered from a previous schema, passing a scan id where a plan id is expected, or truncated ids from logs.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Invalid security scan id: ${scanId}
- Destination paths cannot contain parent traversal or NUL byt
- Shared-folder destination escapes its configured root
- Absolute paths are not allowed in ${scheme}:// URLs: ${rawPa
- Path traversal (..) is not allowed in ${scheme}:// URLs: ${r
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/e03e3127d8e64599.
Report an issue: GitHub.