{"record":{"id":"af6baa7eaf690ef5","repo":"nanocoai/nanoclaw","slug":"no-verb-verbarg-on-res-plural-run-ncl","errorCode":null,"errorMessage":"no verb \"${verbArg}\" on ${res.plural} — run `ncl ${res.plural} help`","messagePattern":"no verb \"(.+?)\" on (.+?) — run `ncl (.+?) help`","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli/commands/help.ts","lineNumber":96,"sourceCode":"        description: `Show ${res.name} resource details; \\`${res.plural} help <verb>\\` for one verb in depth.`,\n        access: 'open',\n        resource: res.plural,\n        parseArgs: (raw) => raw,\n        handler: async (args, ctx) => {\n          const cliScope = await getCliScope(ctx);\n          const lines: string[] = [];\n\n          // `ncl <resource> help <verb>` arrives via the dispatcher's\n          // longest-prefix fallback (`groups-help-create` → `groups-help` +\n          // id=`create`) and renders that verb's deep help — full description,\n          // flags, examples. No new routing. Group-scope auto-fill also puts\n          // the caller's agent group ID into `id` on groups/destinations —\n          // that's not a verb request, so ignore it.\n          const autoFilled = ctx.caller === 'agent' && args.id === ctx.agentGroupId;\n          const verbArg = !autoFilled && typeof args.id === 'string' ? args.id : null;\n          if (verbArg) {\n            const deep = renderVerbHelp(res, verbArg);\n            if (!deep) throw new Error(`no verb \"${verbArg}\" on ${res.plural} — run \\`ncl ${res.plural} help\\``);\n            return deep;\n          }\n\n          lines.push(`${res.plural}: ${res.description}`);\n\n          if (cliScope === 'group' && GROUP_SCOPE_RESOURCES.has(res.plural)) {\n            lines.push('');\n            lines.push('Note: --id and group args are auto-filled to your agent group. You do not need to pass them.');\n          }\n\n          lines.push('');\n\n          // Verbs — one summary line each; deep help is a verb away. Only the\n          // exceptional access levels are tagged: `open` is the unmarked default.\n          const idAutoFilled = cliScope === 'group' && (res.plural === 'groups' || res.plural === 'destinations');\n          const idHint = idAutoFilled ? '' : ' <id>';\n          const tag = (access: string | undefined) => (!access || access === 'open' ? '' : ` [${access}]`);\n          const verbs: string[] = [];","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/cli/commands/help.ts#L78-L114","documentation":"An entry deeper than MAX_PLUGIN_DEPTH levels of nesting throws with its relative path. The depth cap bounds recursion on hostile or pathological trees before any content is read.","triggerScenarios":"A plugin whose directory tree nests deeper than the MAX_PLUGIN_DEPTH constant — e.g. deeply nested node_modules chains or generated build artifacts.","commonSituations":"Committing node_modules or build output into a template; machine-generated trees with pathological nesting; chained extracted archives.","solutions":["Flatten or delete the deep subtree (most often node_modules or build output — templates shouldn't ship them)","Add ignore/exclusion handling in your packaging step so deep trees never enter the plugin","Check MAX_PLUGIN_DEPTH in plugin-dir.ts for the exact limit"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let maxDepth = 0;\nconst walk = (d: string, depth: number) => {\n  maxDepth = Math.max(maxDepth, depth);\n  for (const e of fs.readdirSync(d, { withFileTypes: true })) {\n    if (e.isDirectory()) walk(path.join(d, e.name), depth + 1);\n  }\n};\nwalk(dir, 0);\nif (maxDepth > MAX_PLUGIN_DEPTH) { /* prune deep subtrees before walkPluginDir */ }","typeGuard":null,"tryCatchPattern":"try { walkPluginDir(dir); } catch (e) { if (e instanceof Error && e.message.includes('nesting depth')) { /* delete node_modules/build output and retry */ } else throw e; }","preventionTips":["Never commit node_modules or build artifacts into templates","Prune deep trees during packaging with a depth-aware filter"],"tags":["security","filesystem","limits","templates"],"backgroundTag":"resource-limit-exceeded","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}