From d7436b8b9c1f3132b2ca1def6b1e22225a032854 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 16 Mar 2026 19:28:13 -0400 Subject: [PATCH] llm: catch empty and rate-limited responses as errors Empty stdout and Claude's rate limit message were silently returned as successful 0-byte responses. Now detected and reported as errors. Also skip transcript segments with fewer than 2 assistant messages (rate-limited sessions, stub conversations). Co-Authored-By: Claude Opus 4.6 (1M context) --- poc-memory/src/agents/knowledge.rs | 13 +++++++++++++ poc-memory/src/agents/llm.rs | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/poc-memory/src/agents/knowledge.rs b/poc-memory/src/agents/knowledge.rs index e5cf23c..9a46ff1 100644 --- a/poc-memory/src/agents/knowledge.rs +++ b/poc-memory/src/agents/knowledge.rs @@ -754,6 +754,19 @@ pub fn select_conversation_fragments(n: usize) -> Vec<(String, String)> { if store.is_segment_mined(&session_id, seg_idx as u32, "observation") { continue; } + // Skip segments with too few assistant messages (rate limits, errors) + let assistant_msgs = segment.iter() + .filter(|(_, role, _, _)| role == "assistant") + .count(); + if assistant_msgs < 2 { + continue; + } + // Skip segments that are just rate limit errors + let has_rate_limit = segment.iter().any(|(_, _, text, _)| + text.contains("hit your limit") || text.contains("rate limit")); + if has_rate_limit && assistant_msgs < 3 { + continue; + } let text = format_segment(&segment, 8000); if text.len() > 500 { let id = format!("{}.{}", session_id, seg_idx); diff --git a/poc-memory/src/agents/llm.rs b/poc-memory/src/agents/llm.rs index 4a0a742..099cd7d 100644 --- a/poc-memory/src/agents/llm.rs +++ b/poc-memory/src/agents/llm.rs @@ -152,6 +152,14 @@ fn call_model_with_tools(agent: &str, model: &str, prompt: &str, } if output.status.success() { let response = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if response.is_empty() { + log_usage(agent, model, prompt, "EMPTY", elapsed, false); + return Err("claude returned empty response".into()); + } + if response.contains(": You've hit your limit \u{00b7} resets") { + log_usage(agent, model, prompt, "RATE_LIMITED", elapsed, false); + return Err(format!("rate limited: {}", crate::util::first_n_chars(&response, 200))); + } log_usage(agent, model, prompt, &response, elapsed, true); Ok(response) } else {