thedotmack/claude-mem · warning
Empty observation response, leaving queue intact
Error message
Empty ${this.providerName} observation response, leaving queue intact What it means
This warning is emitted when the provider receives an observation response with no content (and forwardEmptyMessageResponse is false), so processAgentResponse is skipped and the queue message is left intact rather than marked processed. It prevents empty model replies from consuming queued observation requests.
Solutions
- Inspect the upstream response for why content is empty (finish reason, content filter, truncation).
- Set forwardEmptyMessageResponse=true if empty replies should be forwarded to the agent pipeline.
- Verify the base URL/model config points to a valid chat-completions endpoint.
- Retry or re-check the queued observation message; it remains pending and will be reprocessed.
Example fix
// before (provider config)
{ "providerName": "MyProvider" }
// after
{ "providerName": "MyProvider", "forwardEmptyMessageResponse": true } Defensive patterns
Strategy: fallback
Validate before calling
if (!obsResponse || typeof obsResponse.content !== 'string' || obsResponse.content.length === 0) {
// skip processing or enable forwardEmptyMessageResponse
} Type guard
const hasContent = (r: { content?: string | null }): r is { content: string } =>
typeof r.content === 'string' && r.content.trim().length > 0; Try / catch
if (!hasContent(obsResponse) && !provider.forwardEmptyMessageResponse) {
// queue stays intact; re-poll later
} Prevention
- Set forwardEmptyMessageResponse if empty replies are acceptable
- Log upstream finish reasons to catch content filters/truncation early
- Verify base URL and model config for the OpenAI-compatible endpoint
When it happens
Trigger: In processObservationMessage (called from runMessageLoop), the upstream OpenAI-compatible API returns a response whose obsResponse.content is empty/undefined while forwardEmptyMessageResponse is not enabled.
Common situations: Model returning empty completions due to prompt or truncation issues; upstream provider outage or content filter stripping the reply; misconfigured base URL hitting an endpoint that returns empty bodies.
Understand the failure class
Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.
Related errors
- Empty summary response, leaving queue intact
- ActiveServerQueueManager requires…
- CLAUDE_MEM_QUEUE_ENGINE is not "bullmq"
- parse_error
- SDK turn failed before emitting text, re-queueing the…
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/53b9a207568473de.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/worker/OpenAICompatibleProvider.ts:335
if (obsResponse.content) {
// The assistant turn is appended once, by processAgentResponse below.
// Appending it here too stored every reply twice (#3619), inflating the
// window — and therefore every subsequent request — by ~50%.
tokensUsed = obsResponse.tokensUsed || 0;
session.cumulativeInputTokens += Math.floor(tokensUsed * 0.7);
session.cumulativeOutputTokens += Math.floor(tokensUsed * 0.3);
// Both sides or nothing: a backend reporting only one of the two counts
// must not produce a half-real event (input=0 → compression_ratio 0.0).
session.lastUsage = this.buildLastUsage(obsResponse);
}
if (obsResponse.content || this.forwardEmptyMessageResponse) {
await processAgentResponse(
obsResponse.content || '', session, this.dbManager, this.sessionManager,
worker, tokensUsed, originalTimestamp, this.providerName, lastCwd, obsResponse.servedModel ?? config.model, responseContext
);
} else {
logger.warn('SDK', `Empty ${this.providerName} observation response, leaving queue intact`, {
sessionId: session.sessionDbId
});
}
}
private async processSummaryMessage(
session: ActiveSession,
message: { last_assistant_message?: string },
worker: WorkerRef | undefined,
config: TConfig,
mode: ModeConfig,
originalTimestamp: number | null,
lastCwd: string | undefined
): Promise<void> {
if (!session.memorySessionId) {
throw new Error('Cannot process summary: memorySessionId not yet captured. This session may need to be reinitialized.');
}
View on GitHub (pinned to d8bc9755e7)