{"record":{"id":"eba918d88515ed3e","repo":"nanocoai/nanoclaw","slug":"agent-group-not-found-agentgroupid","errorCode":null,"errorMessage":"Agent group not found: ${agentGroupId}","messagePattern":"Agent group not found: (.+?)","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/container-config.ts","lineNumber":385,"sourceCode":"    groupName: group.name,\n    assistantName: row.assistant_name ?? group.name,\n    agentGroupId: group.id,\n    maxMessagesPerPrompt: row.max_messages_per_prompt ?? undefined,\n    model: row.model ?? undefined,\n    effort: row.effort ?? undefined,\n    timezone: row.timezone && isValidTimezone(row.timezone) ? row.timezone : undefined,\n    runtimeTier: parseRuntimeTier(row.runtime_tier, group.name),\n  };\n}\n\n/**\n * Materialize `container.json` from the DB. Called at spawn time so the\n * container always sees fresh config. Returns the `ContainerConfig` for\n * use by the caller (buildMounts, composeSessionSpec, etc.).\n */\nexport async function materializeContainerJson(agentGroupId: string): Promise<ContainerConfig> {\n  const group = await getAgentGroup(agentGroupId);\n  if (!group) throw new Error(`Agent group not found: ${agentGroupId}`);\n\n  const row = await getContainerConfig(agentGroupId);\n  if (!row) throw new Error(`Container config not found for agent group: ${agentGroupId}`);\n\n  const config = configFromDb(row, group);\n\n  const p = path.join(GROUPS_DIR, group.folder, 'container.json');\n  const dir = path.dirname(p);\n  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n  fs.writeFileSync(p, JSON.stringify(config, null, 2) + '\\n');\n\n  return config;\n}\n","sourceCodeStart":367,"sourceCodeEnd":399,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/container-config.ts#L367-L399","documentation":"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.","triggerScenarios":"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.","commonSituations":"Race between group deletion and an inbound message waking a session; scripts caching old group ids; partial uninstall leaving orphaned wiring rows.","solutions":["Verify the group exists: ncl groups list (or SELECT * FROM agent_groups)","If deleted intentionally, clean up sessions/wirings referencing it: ncl wirings list, delete stale rows","If it should exist, recreate/restore the group before retrying spawn"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const group = await getAgentGroup(agentGroupId); if (!group) { await cleanupStaleSessions(agentGroupId); return; }","typeGuard":null,"tryCatchPattern":"try { await materializeContainerJson(id); } catch (err) { if (err.message.includes('Agent group not found')) { logAndDropStaleSession(id); } else throw err; }","preventionTips":["Delete wirings/sessions when deleting a group (ncl groups delete handles this — avoid raw DB deletes)","Check ncl groups list before scripting spawns against cached ids","Monitor routing errors after any group deletion"],"tags":["agent-groups","spawn","db-integrity"],"backgroundTag":"entity-not-found","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}