ruvnet/ruflo · error

RuvBotBridgeConfig.proofSigningKey is required when enablePr

Error message

RuvBotBridgeConfig.proofSigningKey is required when enableProofChain is true

What it means

Thrown inside the bridge's private session:create event handler when RuvBotBridgeConfig.enableProofChain is true but config.proofSigningKey is missing. Every proof-chain entry is signed (the chain is created via createProofChain({ signingKey })), so a key is mandatory. The check happens lazily on the first ruvbot 'session:create' event, not at construction, which is why it can surprise you well after startup.

Source

Thrown at v3/@claude-flow/guidance/src/ruvbot-integration.ts:859

            `Agent manifest ${validation.admissionDecision}: risk=${validation.riskScore}, errors=${validation.errors.length}`,
          );
        }
      }
    }
  }

  /**
   * Handle `session:create` events: initialize a proof chain for the session.
   */
  private async handleSessionCreate(...args: unknown[]): Promise<void> {
    const data = (args[0] ?? {}) as Record<string, unknown>;
    const sessionId = String(data['sessionId'] ?? data['id'] ?? `session-${Date.now()}`);

    this.logEvent('session:create', { sessionId });

    if (this.config.enableProofChain) {
      if (!this.config.proofSigningKey) {
        throw new Error(
          'RuvBotBridgeConfig.proofSigningKey is required when enableProofChain is true',
        );
      }
      const { createProofChain } = await import('./proof.js');
      const chain = createProofChain({ signingKey: this.config.proofSigningKey });
      this.sessionChains.set(sessionId, chain);
    }
  }

  /**
   * Handle `session:end` events: finalize the proof chain and persist.
   */
  private async handleSessionEnd(...args: unknown[]): Promise<void> {
    const data = (args[0] ?? {}) as Record<string, unknown>;
    const sessionId = String(data['sessionId'] ?? data['id'] ?? 'unknown');

    this.logEvent('session:end', { sessionId });

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Provide proofSigningKey in the bridge config whenever enableProofChain is true
  2. Or set enableProofChain: false if signed audit trails are not required in that environment
  3. Validate the pairing (enableProofChain => proofSigningKey present) at startup, before wiring ruvbot events, so it fails fast instead of mid-event

Example fix

// before
new RuvBotGuidanceBridge(ruvbot, { enableProofChain: true }); // no key -> throws on first session:create

// after
new RuvBotGuidanceBridge(ruvbot, {
  enableProofChain: true,
  proofSigningKey: process.env.PROOF_SIGNING_KEY!,
});
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast at startup instead of on the first session:create event
function validateBridgeConfig(cfg: RuvBotBridgeConfig): void {
  if (cfg.enableProofChain && !cfg.proofSigningKey) {
    throw new Error(
      `proofSigningKey required: enableProofChain=true but key is ${cfg.proofSigningKey === '' ? 'empty' : 'unset'}`,
    );
  }
}
validateBridgeConfig(config); // before constructing/wiring the bridge

Type guard

type ProofCapableConfig = RuvBotBridgeConfig & { proofSigningKey: string };
function hasProofKey(cfg: RuvBotBridgeConfig): cfg is ProofCapableConfig {
  return !cfg.enableProofChain || (typeof cfg.proofSigningKey === 'string' && cfg.proofSigningKey.length > 0);
}

Try / catch

// handleSessionCreate is an internal event handler; catch at the event boundary
ruvbot.on('error', (e: Error) => {
  if (e.message.includes('proofSigningKey')) {
    failStartup('PROOF_SIGNING_KEY missing while enableProofChain=true');
  }
});

Prevention

When it happens

Trigger: Constructing RuvBotGuidanceBridge(ruvbot, { enableProofChain: true }) without proofSigningKey, then the wrapped ruvbot emits a 'session:create' event; typical when the enable flag and the key come from different config sources and the key source is empty.

Common situations: proofSigningKey sourced from an env var (e.g. PROOF_SIGNING_KEY) that is set in production but unset in CI/staging while enableProofChain is hardcoded true; async key loading that has not completed before events start flowing; config objects assembled from partials where the key field is dropped.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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