nanocoai/nanoclaw · error · Error

group folder 'groups/${folder}' already exists on disk but n

Error message

group folder 'groups/${folder}' already exists on disk but no agent group claims it — deleting a group never removes its folder, and creating a new group over it would silently adopt the old group's data under a new identity. Move or remove the folder, or pick a different --folder.

What it means

`ncl groups create` refuses to create a group whose folder already exists on disk (groups/<folder>/) when no agent_groups row claims that folder. Deleting a group never removes its folder, so a directory without a DB row is residue from a deleted group; creating over it would silently adopt the old group's data (workspace, memory, skills) under a brand-new group id.

Source

Thrown at src/cli/resources/groups.ts:175

        }
        const folder = args.folder as string;
        if (!folder) throw new Error('--folder is required');
        // The template path validates through createAgentFromTemplate; the bare
        // path used to validate nowhere, minting folders the runtime label
        // grammar refuses at every spawn.
        assertValidGroupFolder(folder);
        const name = (args.name as string) ?? folder;
        const existing = await getAgentGroupByFolder(folder);
        if (existing) {
          await initGroupFilesystem(existing); // ensure a reused group is fully configured too (idempotent; also repairs a missing workspace folder)
          return existing;
        }
        // Fresh-create branch only: a folder on disk with no claiming DB row
        // is deleted-group residue (delete never removes groups/<folder>/) or
        // an operator-placed dir — minting a new id over it would silently
        // re-scope the old group's data under a new identity.
        if (groupFolderExistsOnDisk(folder)) {
          throw new Error(
            `group folder 'groups/${folder}' already exists on disk but no agent group claims it — ` +
              `deleting a group never removes its folder, and creating a new group over it would silently ` +
              `adopt the old group's data under a new identity. Move or remove the folder, or pick a different --folder.`,
          );
        }
        const id = `ag-${randomUUID()}`;
        const group: AgentGroup = { id, name, folder, agent_provider: null, created_at: new Date().toISOString() };
        await createAgentGroup(group);
        // Provision the workspace folder and the `container_configs` row that
        // `getContainerConfig` and the spawn path require. Without this, a
        // group created via `ncl groups create` would throw "Container config
        // not found" on first spawn and stay broken until the host restart
        // backfill ran (#2415). The template branch above provisions its own
        // config + folder in `createAgentFromTemplate`; this covers the bare
        // path. Mirrors what `setup/register.ts` does after creating an agent
        // group via the setup flow. The config row is stamped with the
        // instance default provider (`ensureContainerConfig` inside) — per-group
        // `groups config update --provider` still wins.

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Remove or move the leftover folder: `rm -rf groups/X` (after confirming you don't need its data/memory), then retry the create
  2. Pick a different folder: `ncl groups create --folder X-new`
  3. If you actually want the old data, restore the deleted DB row instead of recreating the group

Example fix

# before
ncl groups delete --id ag-...
ncl groups create --folder my-agent   # throws
# after
mv groups/my-agent groups/my-agent.bak
ncl groups create --folder my-agent
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
const dir = `groups/${folder}`;
if (existsSync(dir)) {
  const claimed = await getAgentGroupByFolder(folder);
  if (!claimed) { /* residue: move/remove before create */ }
}

Type guard

const isClaimedFolder = (r: unknown): r is { id: string } => !!r && typeof (r as any).id === 'string';

Try / catch

try { await createGroup(folder) } catch (e) { if (e instanceof Error && e.message.includes('already exists on disk')) { await renameOld(folder); await createGroup(folder); } else throw e; }

Prevention

When it happens

Trigger: `ncl groups create --folder X` where groups/X/ exists on disk but the agent_groups table has no row with folder=X. Typical after `ncl groups delete --id <id>` was run earlier and groups/X/ was left behind.

Common situations: Delete-then-recreate workflows (delete a group, immediately try to recreate one with the same folder name); operator manually placed a directory under groups/; restoring from a partial backup where the filesystem has folders the DB doesn't know about.

Related errors


AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28). Data as JSON: /api/errors/8821923ba97e25cc. Report an issue: GitHub.