musistudio/claude-code-router · error · Error

No Bot Gateway conversationRef is configured and no inbound

Error message

No Bot Gateway conversationRef is configured and no inbound bot event context is available.

What it means

sendText() needs a conversation reference to address an outbound Bot Gateway message. It first tries runtime-resolved context (inbound event) and falls back to configured conversationRef; when both are absent it cannot know where to deliver and throws. The Gateway requires an explicit destination for proactive (non-reply) sends.

Source

Thrown at packages/core/src/agents/codex/cli-middleware-runtime.ts:5485

  forwardDecision() {
    if (this.config.forwardAllAgentMessages) {
      return { shouldForward: true, reason: "forward_all" };
    }
    if (!this.config.handoff.enabled) {
      return { shouldForward: false, reason: "forwarding_disabled" };
    }
    const presence = evaluateHandoffPresence(this.config.handoff);
    return {
      shouldForward: presence.away,
      reason: presence.away ? presence.reasons.join(", ") : presence.evidence.join(", ")
    };
  }

  async sendText(key, text, params, decision) {
    const conversationRef = this.resolveConversationRef();
    if (!conversationRef) {
      throw new Error("No Bot Gateway conversationRef is configured and no inbound bot event context is available.");
    }
    const outbound = {
      tenantId: this.resolveTenantId(),
      integrationId: this.resolveIntegrationId(),
      conversationRef,
      intent: {
        type: "text",
        text
      },
      idempotencyKey: "ccr:handoff:" + this.config.profileId + ":" + stableBotKey(key)
    };
    await this.sendDurable(outbound, { kind: "handoff", sourceKey: key });
    this.rememberForwarded(key);
    log("bot_gateway_forward_sent", {
      key,
      reason: decision.reason,
      textLen: text.length,
      threadId: params.threadId || "",

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Set conversationRef in the Bot Gateway config so proactive sends have a default destination
  2. If replying to a user, use sendReplyToEvent(event, ...) instead, which derives the ref from the event
  3. Only call sendText() within an inbound event context when no configured ref exists
  4. Validate config on startup and fail fast with a clear message when proactive sending is enabled without conversationRef

Example fix

// before
await gateway.sendText(key, text, params); // throws: no conversationRef

// after
const conversationRef = gateway.resolveConversationRef();
if (conversationRef) {
  await gateway.sendText(key, text, params);
} else {
  await gateway.sendReplyToEvent(event, text, key); // reply path derives ref from event
}
Defensive patterns

Strategy: validation

Validate before calling

const ref = gateway.resolveConversationRef(); if (!ref) throw new ConfigError("set botGateway.conversationRef before proactive sends");

Type guard

function canSendProactively(gateway) { return Boolean(gateway.resolveConversationRef() || gateway.config.conversationRef); }

Try / catch

try { await gateway.sendText(key, text, params); } catch (e) { if (/no conversationRef is configured/i.test(String(e))) { /* fall back to event-reply path or alert config */ } else throw e; }

Prevention

When it happens

Trigger: Calling sendText() outside an inbound bot event flow while the Bot Gateway config has no conversationRef set — e.g. proactive/scheduled messages, background notifications, or a code path that lost the event context.

Common situations: Configuring a bot integration without a default conversationRef and then sending proactive messages; refactoring moved the call outside the event handler; config file missing the gateway section after an upgrade changed its schema.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/4fd77522048f86ee. Report an issue: GitHub.