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

  1. Pass --user with the qualified id: `ncl roles grant --user telegram:alice --role owner`
  2. 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

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


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