nanocoai/nanoclaw · warning

No approval handler registered — row dropped

Error message

No approval handler registered — row dropped

What it means

An approval was approved, but no handler is registered for its action string (getApprovalHandler returned null). The pending row is deleted and the requester is notified that the approval cannot be applied.

Source

Thrown at src/modules/approvals/response-handler.ts:108

  }

  if (!(await transitionPendingApprovalStatus(approval.approval_id, 'pending', 'approved'))) return;

  // Approved — dispatch to the module that registered for this action.
  const notify = (text: string): Promise<void> =>
    writeSessionMessage(session.agent_group_id, session.id, {
      id: `appr-note-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
      kind: 'chat',
      timestamp: new Date().toISOString(),
      platformId: session.agent_group_id,
      channelType: 'agent',
      threadId: null,
      content: JSON.stringify({ text, sender: 'system', senderId: 'system' }),
    });

  const handler = getApprovalHandler(approval.action);
  if (!handler) {
    log.warn('No approval handler registered — row dropped', {
      approvalId: approval.approval_id,
      action: approval.action,
    });
    await notify(`Your ${approval.action} was approved, but no handler is installed to apply it.`);
    await deletePendingApproval(approval.approval_id);
    await notifyApprovalResolved({ approval, session, outcome: 'approve', userId });
    await wakeContainer(session);
    return;
  }

  const payload = JSON.parse(approval.payload);
  try {
    await handler({ session, payload, approval, userId, notify });
    log.info('Approval handled', { approvalId: approval.approval_id, action: approval.action, userId });
  } catch (err) {
    log.error('Approval handler threw', { approvalId: approval.approval_id, action: approval.action, err });
    await notify(
      `Your ${approval.action} was approved, but applying it failed: ${err instanceof Error ? err.message : String(err)}.`,

View on GitHub (pinned to 294ef2aee8)

Solutions

  1. Identify the action name from the log and verify the module that registers its handler is installed and imported
  2. Re-request the approval so a fresh row with a supported action is created
  3. Clean stale pending_approvals rows left over from an older version
Defensive patterns

Strategy: validation

Validate before calling

if (!getApprovalHandler(action)) {
  throw new Error(`No handler for approval action '${action}' — register it before requesting approval`);
}

Type guard

const isRegisteredAction = (a: string): boolean => getApprovalHandler(a) !== null;

Prevention

When it happens

Trigger: A pending_approval row exists with an 'action' value whose handler was never registered at startup; a plugin/module that registers the handler failed to load; action renamed between versions leaving stale rows.

Common situations: Upgrading NanoClaw where an action was renamed; a skill-installed module that registers approval handlers missing or failed to import; hand-inserted pending rows.

Related errors


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