nanocoai/nanoclaw · error · Error
--user is required
Error message
--user is required
What it means
Thrown by `ncl roles grant` when the --user flag is missing. Granting a role inserts into user_roles keyed by user_id, which must be the channel-qualified identity (<channel>:<handle>).
Source
Thrown at src/cli/resources/roles.ts:38
name: 'agent_group_id',
type: 'string',
description:
'Null = global (all groups). A specific ID limits the role to that group. Owner must always be null.',
},
{ name: 'granted_by', type: 'string', description: 'Who granted this role. Informational.' },
{ name: 'granted_at', type: 'string', description: 'Auto-set.' },
],
operations: { list: 'open' },
customOperations: {
grant: {
access: 'approval',
description: 'Grant a role. Use --user, --role, and optionally --group for scoped admin.',
handler: async (args) => {
const userId = args.user as string;
const role = args.role as string;
const groupId = (args.group as string) ?? null;
const grantedBy = (args.granted_by as string) ?? null;
if (!userId) throw new Error('--user is required');
if (!role || !['owner', 'admin'].includes(role)) throw new Error('--role must be owner or admin');
if (role === 'owner' && groupId) throw new Error('owner role is always global (do not pass --group)');
await getDb().run(
`INSERT INTO user_roles (user_id, role, agent_group_id, granted_by, granted_at)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT DO NOTHING`,
userId,
role,
groupId,
grantedBy,
new Date().toISOString(),
);
return { user_id: userId, role, agent_group_id: groupId };
},
},
revoke: {
access: 'approval',
description: 'Revoke a role. Use --user, --role, and --group if scoped.',View on GitHub (pinned to 294ef2aee8)
Solutions
- Pass --user with the qualified id: `ncl roles grant --user telegram:alice --role owner`
- Resolve your identity first via `ncl users list` or the /init-first-agent flow
Example fix
// before ncl roles grant --role owner // after ncl roles grant --user telegram:alice --role owner
Defensive patterns
Strategy: validation
Validate before calling
if (!userId?.includes(':')) throw new Error('--user must be <channel>:<handle>'); Type guard
const isQualifiedUserId = (s) => /^[a-z0-9-]+:[A-Za-z0-9_.-]+$/.test(s);
Prevention
- Resolve your channel identity before granting roles
- Prefer /init-first-agent for owner bootstrap
When it happens
Trigger: Running `ncl roles grant --role owner` without --user; empty user variable in a bootstrap script.
Common situations: First-install owner bootstrap where the operator forgets to resolve their channel identity first (see /init-first-agent); using a bare handle instead of the qualified id elsewhere in the same command.
Related errors
- owner role is always global (do not pass --group)
- role not found
- ${def.name} id is required
- --${col.name.replace(/_/g, '-')} is required
- --folder is required
AI-assisted analysis of nanocoai/nanoclaw@294ef2aee8 (2026-08-28).
Data as JSON: /api/errors/b7e58f4657fea10c.
Report an issue: GitHub.