EveryInc/compound-engineering-plugin · error · Error
${context.collectionPath} points outside a Compound Engineer
Error message
${context.collectionPath} points outside a Compound Engineering checkout; refusing to remove it What it means
removeLocalCollection() refuses to delete a symlink that resolves to a skills directory outside any Compound Engineering checkout ('unrelated' state). This prevents the tool from destroying a symlink owned by a different project or plugin that merely occupies the collection path.
Source
Thrown at src/dev/codex-dev.ts:425
): Promise<void> {
if (previous.kind === "absent") {
await removeManagedCollectionLink(context.collectionPath, activatedTarget, { ignoreChanges: true })
return
}
await replaceManagedCollectionLink(context.collectionPath, previous.target, {
kind: "valid",
target: activatedTarget,
})
}
export async function removeLocalCollection(context: CodexDevContext): Promise<boolean> {
const state = await inspectLocalCollection(context)
if (state.kind === "absent") return false
if (state.kind === "collision") {
throw new Error(`${context.collectionPath} exists and is not a symlink; refusing to remove it`)
}
if (state.kind === "unrelated") {
throw new Error(`${context.collectionPath} points outside a Compound Engineering checkout; refusing to remove it`)
}
if (state.kind === "broken") {
throw new Error(`${context.collectionPath} is a broken symlink; refusing to remove it automatically`)
}
await removeManagedCollectionLink(context.collectionPath, state.target)
return true
}
function parseJson<T>(result: CommandResult, label: string): T {
try {
return JSON.parse(result.stdout) as T
} catch (error) {
throw new Error(`${label} returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`)
}
}
async function runCodex(
context: CodexDevContext,View on GitHub (pinned to c9c10f8c75)
Solutions
- Check the link target: `readlink <collectionPath>` and `realpath <collectionPath>`
- If it is another tool's symlink, remove it manually with `rm <collectionPath>` after confirming
- If it should be a Compound Engineering checkout, restore the missing repo marker files or point it at the correct checkout, then re-run
- Use `bun run codex:dev -- status` to see the resolved state before deciding
Example fix
# before $ bun run codex:dev -- remote # Error: ... points outside a Compound Engineering checkout; refusing to remove it # after $ readlink /path/to/CODEX_HOME/skills/compound-engineering-local $ rm /path/to/CODEX_HOME/skills/compound-engineering-local # verified as another tool's link $ bun run codex:dev -- remote
Defensive patterns
Strategy: validation
Validate before calling
const state = await inspectLocalCollection(context);
if (state.kind === "unrelated") {
console.log(`link targets ${state.resolvedTarget}; verify ownership before removing manually`);
return;
} Type guard
function isManagedLink(s: { kind: string }): boolean {
return s.kind === "absent" || s.kind === "valid" || s.kind === "broken";
} Try / catch
try {
await removeLocalCollection(context);
} catch (e) {
if (String(e).includes("points outside")) {
console.error("foreign symlink: inspect with readlink and remove manually only if it is yours");
} else throw e;
} Prevention
- Do not retarget the collection symlink to other repositories
- Keep the Compound Engineering checkout marker files intact at the link target
- Confirm a foreign link's owner before deleting it manually
When it happens
Trigger: collectionPath is a symlink whose realpath does not pass assertCompoundEngineeringRepo(), or its basename is not 'skills' — e.g. it points at another repo's directory — and removeLocalCollection() (or switchToRemote / removeCodexDevInstallation) is called.
Common situations: The symlink was retargeted by hand or by another tool to a different checkout; the target repo's marker files were removed so it no longer registers as a Compound Engineering checkout; multiple plugins competing for the same skills path.
Related errors
- ${context.collectionPath} exists and is not a symlink; refus
- ${context.collectionPath} is a broken symlink; refusing to o
- ${collectionPath} changed since it was inspected; refusing t
- ${collectionPath} changed since it was inspected; refusing t
- ${context.collectionPath} is a broken symlink; refusing to r
AI-assisted analysis of EveryInc/compound-engineering-plugin@c9c10f8c75 (2026-08-31).
Data as JSON: /api/errors/8b16d714a2516042.
Report an issue: GitHub.