EveryInc/compound-engineering-plugin · error · Error
Cannot switch to local mode while the local collection is ${
Error message
Cannot switch to local mode while the local collection is ${previous.kind} What it means
switchToLocal() only proceeds when the collection path is 'absent' or already a 'valid' managed link. Any other state (collision, unrelated, broken) is rejected up front with this error, so the caller fixes the path state before activation can be attempted.
Source
Thrown at src/dev/codex-dev.ts:560
plugins.some((plugin) => plugin.pluginId === OFFICIAL_PLUGIN_ID) ||
(await isOfficialPluginConfigured(context))
) {
await runCodex(context, runner, ["plugin", "remove", OFFICIAL_PLUGIN_ID, "--json"])
}
await removePlugins(
context,
runner,
plugins.filter((plugin) => plugin.pluginId !== OFFICIAL_PLUGIN_ID),
)
}
export async function switchToLocal(
context: CodexDevContext,
runner: CommandRunner = new BunCommandRunner(),
): Promise<CodexDevStatus> {
const previous = await inspectLocalCollection(context)
if (previous.kind !== "absent" && previous.kind !== "valid") {
throw new Error(`Cannot switch to local mode while the local collection is ${previous.kind}`)
}
const activatedTarget = await fs.realpath(context.skillsRoot)
await activateLocalCollection(context)
try {
const plugins = await listCompoundEngineeringPlugins(context, runner)
await removeLocalPluginConflicts(context, runner, plugins)
const status = await inspectCodexDevStatus(context, runner)
if (status.mode !== "local") {
throw new Error(`Could not verify local Codex development mode (reported ${status.mode})`)
}
return status
} catch (error) {
await restoreLocalCollection(context, previous, activatedTarget)
throw error
}
}
async function listMarketplaces(context: CodexDevContext, runner: CommandRunner): Promise<Marketplace[]> {View on GitHub (pinned to c9c10f8c75)
Solutions
- Run `bun run codex:dev -- status` to see the reported state
- For 'collision': back up and remove the non-symlink directory/file at collectionPath yourself, then retry
- For 'broken': delete the dangling symlink (`rm <collectionPath>`) or restore the missing checkout, then retry
- For 'unrelated': re-point or remove the foreign symlink once confirmed it is not needed, then retry
Example fix
# before (dangling link from a deleted checkout) $ bun run codex:dev -- local // Error: Cannot switch to local mode while the local collection is broken # after $ rm /path/to/CODEX_HOME/skills/compound-engineering-local $ bun run codex:dev -- local # now state is 'absent' and activation proceeds
Defensive patterns
Strategy: validation
Validate before calling
const state = await inspectLocalCollection(context);
if (state.kind !== "absent" && state.kind !== "valid") {
// remediate first: rm dangling/foreign links, move aside real dirs
console.warn(`collection is ${state.kind}; fix before switching to local`);
} else {
await switchToLocal(context);
} Type guard
function canSwitchToLocal(s: { kind: string }): boolean {
return s.kind === "absent" || s.kind === "valid";
} Try / catch
try {
await switchToLocal(context);
} catch (e) {
if (String(e).includes("Cannot switch to local mode")) {
const kind = String(e).match(/collection is (\w+)/)?.[1];
console.error(`remediate state '${kind}' (see status), then retry`);
} else throw e;
} Prevention
- Check `bun run codex:dev -- status` before every mode switch
- Keep the checkout path stable so links never dangle
- Remove foreign or manual entries at the collection path before installing
When it happens
Trigger: Calling switchToLocal() (via runCodexDevCommand or status-driven flows) when inspectLocalCollection returns kind='collision' (real file/dir), 'unrelated' (symlink outside a CE checkout), or 'broken' (dangling symlink).
Common situations: A real skills directory or another plugin's symlink already occupies the collection path; the previous local checkout was deleted leaving a dangling link; a hand-made symlink to the wrong repository.
Related errors
- ${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} exists and is not a symlink; refus
- ${context.collectionPath} points outside a Compound Engineer
AI-assisted analysis of EveryInc/compound-engineering-plugin@c9c10f8c75 (2026-08-31).
Data as JSON: /api/errors/11f98a8ca13d13c0.
Report an issue: GitHub.