nanocoai/nanoclaw · critical · Error

Agent group not found: ${agentGroupId}

Error message

Agent group not found: ${agentGroupId}

What it means

materializeContainerJson looks up the agent group by id before building container.json; a missing row means the id is unknown (deleted group, wrong id, or central DB pointing at stale data). Thrown at spawn time or whenever container config is materialized.

Source

Thrown at src/container-config.ts:385

    groupName: group.name,
    assistantName: row.assistant_name ?? group.name,
    agentGroupId: group.id,
    maxMessagesPerPrompt: row.max_messages_per_prompt ?? undefined,
    model: row.model ?? undefined,
    effort: row.effort ?? undefined,
    timezone: row.timezone && isValidTimezone(row.timezone) ? row.timezone : undefined,
    runtimeTier: parseRuntimeTier(row.runtime_tier, group.name),
  };
}

/**
 * Materialize `container.json` from the DB. Called at spawn time so the
 * container always sees fresh config. Returns the `ContainerConfig` for
 * use by the caller (buildMounts, composeSessionSpec, etc.).
 */
export async function materializeContainerJson(agentGroupId: string): Promise<ContainerConfig> {
  const group = await getAgentGroup(agentGroupId);
  if (!group) throw new Error(`Agent group not found: ${agentGroupId}`);

  const row = await getContainerConfig(agentGroupId);
  if (!row) throw new Error(`Container config not found for agent group: ${agentGroupId}`);

  const config = configFromDb(row, group);

  const p = path.join(GROUPS_DIR, group.folder, 'container.json');
  const dir = path.dirname(p);
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
  fs.writeFileSync(p, JSON.stringify(config, null, 2) + '\n');

  return config;
}

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Verify the group exists: ncl groups list (or SELECT * FROM agent_groups)
  2. If deleted intentionally, clean up sessions/wirings referencing it: ncl wirings list, delete stale rows
  3. If it should exist, recreate/restore the group before retrying spawn
Defensive patterns

Strategy: try-catch

Validate before calling

const group = await getAgentGroup(agentGroupId); if (!group) { await cleanupStaleSessions(agentGroupId); return; }

Try / catch

try { await materializeContainerJson(id); } catch (err) { if (err.message.includes('Agent group not found')) { logAndDropStaleSession(id); } else throw err; }

Prevention

When it happens

Trigger: Spawning a container for an agentGroupId that was deleted (ncl groups delete) while a session/message still references it; passing a malformed id; central DB reset while sessions persist.

Common situations: Race between group deletion and an inbound message waking a session; scripts caching old group ids; partial uninstall leaving orphaned wiring rows.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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