nanocoai/nanoclaw · error · Error

--id is required

Error message

--id is required

What it means

Thrown by `ncl groups delete` when no --id flag is given. Unlike agent-called commands, host-side delete has no caller context to auto-fill the group id from, so the id must be supplied explicitly.

Source

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

        return getAgentGroupByFolder(folder);
      },
      // The restamp path returns a plan that wants the aligned-lines view;
      // everything else keeps the generic JSON rendering.
      formatHuman: (data) =>
        data !== null && typeof data === 'object' && 'changes' in data && 'plugin' in data
          ? formatRestampResult(data as RestampResult)
          : JSON.stringify(localizeIsoTimestamps(data), null, 2),
    },
    delete: {
      access: 'approval',
      description:
        'Delete an agent group and its dependent rows (sessions, destinations, approvals, role grants, ' +
        'memberships, channel wirings). FK-ordered cascade in a single transaction. ' +
        'Use --id <group-id>. Out of scope: killing running containers, on-disk cleanup of groups/<folder>/ and data/v2-sessions/<group-id>/. ' +
        'The leftover groups/<folder>/ blocks re-creating a group under the same folder name until it is moved or removed.',
      handler: async (args) => {
        const id = args.id as string;
        if (!id) throw new Error('--id is required');
        const db = getDb();

        // Verify the group exists before doing anything — preserves the
        // genericDelete behaviour of throwing "not found" for unknown IDs.
        const exists = await db.get('SELECT 1 FROM agent_groups WHERE id = ? LIMIT 1', id);
        if (!exists) throw new Error(`group not found: ${id}`);

        const hasAgentDestinations = await hasTable(db, 'agent_destinations');
        const hasPendingApprovals = await hasTable(db, 'pending_approvals');

        // FK-ordered cascade. The async driver transaction rolls
        // back the whole thing if any statement throws (e.g. an FK constraint
        // we missed), so the central DB stays consistent. The `removed` counts
        // are sourced from each DELETE's `changes` so they describe exactly
        // what the transaction did, not a separate pre-flight snapshot.
        const removed = await db.transaction(async () => {
          const counts = {
            sessions: 0,

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Run `ncl groups list` to find the group id, then `ncl groups delete --id ag-<uuid>`
  2. Quote and default-check script variables: `: "${GROUP_ID:?GROUP_ID not set}"`
  3. Note delete does NOT remove groups/<folder>/ or data/v2-sessions/<group-id>/ — clean those up manually afterwards

Example fix

# before
ncl groups delete
# after
ncl groups list
ncl groups delete --id ag-1234abcd-...
Defensive patterns

Strategy: validation

Validate before calling

: "${GROUP_ID:?GROUP_ID not set}"
ncl groups delete --id "$GROUP_ID"

Type guard

const isGroupId = (v: unknown): v is string => typeof v === 'string' && /^ag-[0-9a-f-]{36}$/.test(v);

Try / catch

try { await deleteGroup(id) } catch (e) { if (e instanceof Error && e.message === '--id is required') { /* usage bug, fix caller */ } throw e; }

Prevention

When it happens

Trigger: Running `ncl groups delete` with no --id, or a script whose --id variable expanded to empty (`ncl groups delete --id $GROUP_ID` with GROUP_ID unset).

Common situations: Shell scripts with unset/empty variables; operators assuming delete works on a 'current' or default group; CI jobs where the id lookup step failed silently and passed an empty string.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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