musistudio/claude-code-router · error
No Bot Gateway conversationRef is available for media respon
Error message
No Bot Gateway conversationRef is available for media response.
What it means
Thrown by sendMediaToEvent when the middleware cannot resolve a Bot Gateway conversationRef for the event. The code first tries conversationRefFromEvent(event) and then falls back to this.config.conversationRef; if both are undefined there is no routing address to deliver the media payload to, so it refuses to send.
Source
Thrown at packages/core/src/agents/codex/cli-middleware-runtime.ts:5539
}
}
async sendCardToEvent(event, card, fallbackText, key) {
await this.ensureStarted();
const conversationRef = conversationRefFromEvent(event) || this.config.conversationRef;
if (!conversationRef) throw new Error("No Bot Gateway conversationRef is available for card response.");
const language = botLanguageForEvent(this.config.language, event);
const localizedFallback = localizeBotReply(fallbackText, language);
const localizedCard = language === "zh-CN" ? localizeBotCard(card) : card;
const outbound = this.outboundForEvent(event, conversationRef, { type: "card", card: localizedCard, fallbackText: localizedFallback }, key);
await this.sendDurable(outbound, { kind: "card", sourceKey: key });
}
async sendMediaToEvent(event, media, caption, key) {
if (!this.config.mediaEnabled) return;
await this.ensureStarted();
const conversationRef = conversationRefFromEvent(event) || this.config.conversationRef;
if (!conversationRef) throw new Error("No Bot Gateway conversationRef is available for media response.");
const fallbackText = caption || media.filename || media.url || "Attachment";
const outbound = this.outboundForEvent(event, conversationRef, { type: "media", media, caption, fallbackText }, key);
await this.sendDurable(outbound, { kind: "media", sourceKey: key });
}
async sendStreamToEvent(event, streamId, text, final, key) {
if (!this.config.streamReplies || !text) return;
await this.ensureStarted();
const conversationRef = conversationRefFromEvent(event) || this.config.conversationRef;
if (!conversationRef) return;
const outbound = this.outboundForEvent(event, conversationRef, {
type: "stream_text",
streamId,
text,
final: Boolean(final),
fallbackText: text
}, key + ":" + (final ? "final" : stableBotKey(text.slice(-160))));
await this.sendDurable(outbound, { kind: "stream", sourceKey: key });View on GitHub (pinned to 99f24806c6)
Solutions
- Pass a conversationRef in the middleware config: new CodexCliMiddlewareRuntime({ conversationRef, ... }) so a fallback always exists
- Ensure the event object actually contains the Bot Gateway conversationRef payload before calling sendMediaToEvent
- If the event is optional, guard with conversationRefFromEvent(event) ?? config.conversationRef before calling and skip sending when absent
Example fix
// before
await runtime.sendMediaToEvent(event, media, caption);
// after
if (conversationRefFromEvent(event) || runtime.config.conversationRef) {
await runtime.sendMediaToEvent(event, media, caption);
} else {
// log and skip media delivery
} Defensive patterns
Strategy: validation
Validate before calling
const ref = conversationRefFromEvent(event) ?? runtime.config.conversationRef;
if (!ref) {
// skip media delivery, log context
return;
}
await runtime.sendMediaToEvent(event, media, caption, key); Type guard
function hasConversationRef(event: unknown): boolean {
return conversationRefFromEvent(event as never) != null;
} Try / catch
try { await runtime.sendMediaToEvent(event, media, caption); } catch (e) { if (e instanceof Error && e.message.includes('conversationRef')) { /* degrade gracefully */ } else throw e; } Prevention
- Always configure a default conversationRef on the middleware
- Validate events carry a conversationRef before processing media
- Log event shape when the ref is missing to spot upstream payload changes
When it happens
Trigger: Calling sendMediaToEvent(event, media, ...) with mediaEnabled=true on an event that carries no conversation reference (e.g. a synthetic or webhook event without a conversationRef field) while the runtime was started without config.conversationRef, or before conversationRef was populated.
Common situations: Testing with mock/seeded events that omit conversationRef; misconfigured middleware where the default conversationRef option was not passed at construction; processing events from a different channel type that doesn't embed a conversationRef.
Related errors
- No Bot Gateway conversationRef is configured and no inbound
- No Bot Gateway conversationRef is available for inbound bot
- No Bot Gateway conversationRef is available for card respons
- Video fallback model ${selector} uses ${target.protocol}, bu
- A media model must be selected.
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/d66ac61eee61f911.
Report an issue: GitHub.