EveryInc/compound-engineering-plugin · warning
Ignoring unreadable Pi install manifest at ${manifestPath}.
Error message
Ignoring unreadable Pi install manifest at ${manifestPath}. What it means
Emitted by the Pi target's readInstallManifest when the Pi install manifest exists but fails to parse or read with an error other than ENOENT. Like the managed variant, the function swallows the error, warns, and returns null so Pi installation continues without stale owned-file tracking. ENOENT is silently treated as 'no manifest yet'.
Source
Thrown at src/targets/pi.ts:355
const promptsRoot = paths?.promptsDir ?? managedDir
const extensionsRoot = paths?.extensionsDir ?? managedDir
const agentsRoot = paths?.agentsDir ?? managedDir
// `agents` was added in v2.69+; accept missing/omitted to stay
// backward-compatible with v2.x manifests that only tracked skills,
// prompts, and extensions. Drop non-array values defensively.
const rawAgents = Array.isArray(parsed.agents) ? parsed.agents : []
return {
version: 1,
pluginName,
skills: filterSafePiManifestEntries(parsed.skills, skillsRoot, manifestPath, "skills"),
prompts: filterSafePiManifestEntries(parsed.prompts, promptsRoot, manifestPath, "prompts"),
extensions: filterSafePiManifestEntries(parsed.extensions, extensionsRoot, manifestPath, "extensions"),
agents: filterSafePiManifestEntries(rawAgents, agentsRoot, manifestPath, "agents"),
}
}
} catch (err) {
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
console.warn(`Ignoring unreadable Pi install manifest at ${manifestPath}.`)
}
}
return null
}
function filterSafePiManifestEntries(
entries: unknown[],
rootDir: string,
manifestPath: string,
group: string,
): string[] {
const safe: string[] = []
for (const entry of entries) {
if (isSafeManagedPath(rootDir, entry)) {
safe.push(entry)
} else {
console.warn(
`Dropping unsafe Pi install-manifest entry in ${manifestPath} (group "${group}"): ${JSON.stringify(entry)}`,View on GitHub (pinned to c9c10f8c75)
Solutions
- Delete the unreadable Pi manifest so the next run starts clean (ENOENT path).
- Fix the JSON syntax or permissions on manifestPath.
- Reinstall the Pi plugin target to regenerate the manifest.
- Check for concurrent installs that may have raced while writing the manifest.
Example fix
// before Pi manifest with a trailing comma -> warning on every run // after rm <manifestPath> && reinstall // fresh valid manifest
Defensive patterns
Strategy: fallback
Validate before calling
const raw = await readFile(manifestPath, "utf8").catch(() => null);
const valid = raw !== null && (() => { try { JSON.parse(raw); return true; } catch { return false; } })(); Try / catch
const manifest = await readPiInstallManifest(manifestPath);
if (manifest === null) {
// absent or unreadable: treat as fresh install, manifest will be rewritten
} Prevention
- Avoid concurrent Pi installs racing on the same manifest.
- Validate JSON after any manual edit (jq . manifest.json).
- Keep manifest file permissions intact when syncing home directories.
- Delete rather than partially repair a broken manifest.
When it happens
Trigger: Calling readPiInstallManifest / readInstallManifestWithLegacyFallback / owned when the Pi manifest at manifestPath contains invalid JSON, is unreadable due to permissions, or fails I/O with a non-ENOENT errno.
Common situations: Manifest truncated by an interrupted Pi install; hand-edited JSON; permission mismatch after copying a home directory; format drift from an older plugin version.
Related errors
- Ignoring unreadable install manifest at ${manifestPath}.
- Local plugin path not found: ${directPath}
- Local plugin path not found: ${directPath}
- Plugin directory not found: ${pluginPath}
- Could not read ${filePath}: ${error instanceof Error ? error
AI-assisted analysis of EveryInc/compound-engineering-plugin@c9c10f8c75 (2026-08-31).
Data as JSON: /api/errors/7eb7b61c069d2405.
Report an issue: GitHub.