ruvnet/ruflo · error

Capability ${capability.id} is not delegatable

Error message

Capability ${capability.id} is not delegatable

What it means

CapabilityAuthority.delegate() mints a child capability from a parent, but only if the parent was granted with `delegatable: true`. Delegatability is an explicit opt-in at grant time, not a default, so this error means the capability's issuer never allowed it to be passed on. It is the first of three parent-state checks (delegatable, not revoked, not expired).

Source

Thrown at v3/@claude-flow/guidance/src/capabilities.ts:229

    return restricted;
  }

  /**
   * Delegate a capability to another agent.
   *
   * Creates a child capability with the new grantedTo agent. The parent
   * capability must have delegatable=true. Optional further restrictions
   * can be applied during delegation.
   *
   * @throws Error if the capability is not delegatable
   */
  delegate(
    capability: Capability,
    toAgentId: string,
    restrictions?: Partial<Capability>,
  ): Capability {
    if (!capability.delegatable) {
      throw new Error(
        `Capability ${capability.id} is not delegatable`
      );
    }

    if (capability.revoked) {
      throw new Error(
        `Cannot delegate revoked capability ${capability.id}`
      );
    }

    if (capability.expiresAt !== null && capability.expiresAt <= Date.now()) {
      throw new Error(
        `Cannot delegate expired capability ${capability.id}`
      );
    }

    const delegated: Capability = {
      ...capability,

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Ask the original grantor to re-grant with `delegatable: true` (narrow actions/resources if needed)
  2. Skip delegation: have the parent capability's holder perform the action directly
  3. Mint a fresh capability for the target agent from the authority instead of delegating

Example fix

// before
const child = authority.delegate(parentCap, 'agent-b'); // parentCap.delegatable === false → throws

// after
// grantor re-issues with delegation allowed:
const parentCap = authority.grant({ ..., delegatable: true });
const child = authority.delegate(parentCap, 'agent-b');
Defensive patterns

Strategy: validation

Validate before calling

if (!capability.delegatable) {
  // request a delegatable re-grant or act directly — do not call delegate()
}

Type guard

const isDelegatable = (c: Capability): boolean =>
  c.delegatable === true && c.revoked !== true &&
  (c.expiresAt === null || c.expiresAt > Date.now());

Prevention

When it happens

Trigger: Calling `delegate(cap, agentB)` on a capability granted without `delegatable: true`; composing workflows that assume any capability can be handed to a sub-agent.

Common situations: Default grants (least-privilege) omit delegatable; a security review tightened grants to non-delegatable and downstream delegation code now fails; capabilities granted by another team/service without delegation rights.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/44d6a438bbd1f0c0. Report an issue: GitHub.