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
- Run `ncl groups list` to find the group id, then `ncl groups delete --id ag-<uuid>`
- Quote and default-check script variables: `: "${GROUP_ID:?GROUP_ID not set}"`
- 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
- Always resolve the id from `ncl groups list` programmatically instead of hardcoding
- Set shell 'unset variable' guards in delete scripts
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
- --folder is required
- group not found: ${id}
- ${def.name} id is required
- --${col.name.replace(/_/g, '-')} is required
- group folder 'groups/${folder}' already exists on disk but n
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/3691ae19ff8b76db.
Report an issue: GitHub.