can1357/oh-my-pi · error · Error

Invalid security store scan index at ${this.#indexPath()}

Error message

Invalid security store scan index at ${this.#indexPath()}

What it means

#readIndex additionally validates the shape of the index: scanIds must be an array of strings (and planIds, when present, likewise). If the JSON parses but its scanIds field is missing or of the wrong type, the index is considered corrupt and the store throws instead of operating on an unusable index.

Source

Thrown at packages/coding-agent/src/security/store.ts:225

			if (!isEnoent(error)) throw error;
			await this.#writeIndex({
				schemaVersion: STORE_SCHEMA_VERSION,
				projectKey: this.#projectKey,
				repositoryRoot: this.#repositoryRoot,
				scanIds: [],
				planIds: [],
				updatedAt: new Date().toISOString(),
			});
		}
	}

	async #readIndex(): Promise<SecurityStoreIndex> {
		const value = (await readJsonFile(this.#indexPath())) as Partial<SecurityStoreIndex>;
		if (value.schemaVersion !== STORE_SCHEMA_VERSION || value.projectKey !== this.#projectKey) {
			throw new Error(`Unsupported security store index at ${this.#indexPath()}`);
		}
		if (!Array.isArray(value.scanIds) || !value.scanIds.every(id => typeof id === "string")) {
			throw new Error(`Invalid security store scan index at ${this.#indexPath()}`);
		}
		if (
			value.planIds !== undefined &&
			(!Array.isArray(value.planIds) || !value.planIds.every(id => typeof id === "string"))
		) {
			throw new Error(`Invalid security store plan index at ${this.#indexPath()}`);
		}
		return { ...value, planIds: value.planIds ?? [] } as SecurityStoreIndex;
	}

	async #writeIndex(index: SecurityStoreIndex): Promise<void> {
		await writeSecurityFileAtomic(this.#indexPath(), `${JSON.stringify(index, null, 2)}\n`);
	}

	async #putBundleUnlocked(input: SecurityScanBundle): Promise<void> {
		const bundle = parseSecurityScanBundle(input);
		if (bundle.scan.projectKey !== this.#projectKey) {
			throw new Error(`Security scan project key ${bundle.scan.projectKey} does not match ${this.#projectKey}`);

View on GitHub (pinned to 9690622007)

Solutions

  1. Delete or restore a valid scans/index.json so #ensureIndex rebuilds it
  2. Recreate the index by re-running scans, or restore from backup/version control if tracked
  3. Fix scanIds to be an array of secscan_ id strings if you are intentionally hand-repairing
  4. Investigate what corrupted the file (concurrent writers, disk issues) before re-running

Example fix

// before
// index.json: { schemaVersion: 2, projectKey: "k", scanIds: null }
// after
// index.json: { schemaVersion: 2, projectKey: "k", scanIds: ["secscan_1a2b"] }
Defensive patterns

Strategy: try-catch

Validate before calling

const idx = await Bun.file(indexPath).json();
if (!Array.isArray(idx.scanIds)) console.warn("scan index corrupt");

Type guard

null

Try / catch

try { openStore(dir); } catch (e) { if (String(e.message).startsWith("Invalid security store scan index")) { await fs.rm(indexPath); } else throw e; }

Prevention

When it happens

Trigger: Reading index.json where scanIds is undefined/null/an object or contains non-string entries — typically from manual edits, a partial write/crash, or corruption; note the schemaVersion/projectKey check already passed.

Common situations: Hand-edited index files, concurrent writes without locking, disk-full truncation producing valid JSON with wrong fields, or copying an index between projects that kept one project's arrays.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/9ca49219d4ecb80e. Report an issue: GitHub.