From e05af9256302444e161cfbdc71ef0c74c9caea7f Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Wed, 7 Oct 2026 07:56:37 +0300 Subject: [PATCH] fix(bus): detect DashScope input length range as context overflow DashScope rejects over-long prompts with "Range of input length should be [1, 98304]", which was not recognised as a context window overflow. Added the phrasing to the hint list and documented that this matcher is a deliberate copy of tinyinference's, kept in sync by hand because the contract crate stays dependency-free. Auto-committed-on: dragonfly Co-authored-by: Medulla --- crates/tinychannels-bus/src/context.rs | 10 ++++++++++ crates/tinychannels-bus/src/context_tests.rs | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/crates/tinychannels-bus/src/context.rs b/crates/tinychannels-bus/src/context.rs index 74abe6b..c1e0a5c 100644 --- a/crates/tinychannels-bus/src/context.rs +++ b/crates/tinychannels-bus/src/context.rs @@ -162,6 +162,13 @@ pub fn should_skip_memory_context_entry(key: &str, content: &str) -> bool { /// - **Token-count phrases** ("too many tokens", "token limit exceeded") collide /// with per-minute token *rate* limits, which are transient. They count as /// overflow only when no rate-limit marker is present. +/// +/// This is a deliberate copy of `is_context_window_exceeded_message` in +/// tinyinference's `crates/tinyinference-llm/src/failure.rs`, and its match +/// list must track that function. It is duplicated rather than imported +/// because this is the contract crate, which stays dependency-free and cannot +/// take a dependency on the inference stack. When a provider phrasing is added +/// there, add it here with the same test string. pub fn is_context_window_overflow_message(err: &str) -> bool { let lower = err.to_ascii_lowercase(); @@ -174,6 +181,9 @@ pub fn is_context_window_overflow_message(err: &str) -> bool { "prompt is too long", "input is too long", "greater than the context length", + // Alibaba / DashScope (Qwen): `"Range of input length should be + // [1, 98304]"` — the window is the range's upper bound. + "range of input length should be", ]; if CONTEXT_HINTS.iter().any(|hint| lower.contains(hint)) { return true; diff --git a/crates/tinychannels-bus/src/context_tests.rs b/crates/tinychannels-bus/src/context_tests.rs index 0aa4030..e255a42 100644 --- a/crates/tinychannels-bus/src/context_tests.rs +++ b/crates/tinychannels-bus/src/context_tests.rs @@ -105,6 +105,21 @@ fn context_overflow_matches_lmstudio_n_keep_body() { )); } +#[test] +fn context_overflow_matches_dashscope_input_length_range() { + let body = "Provider returned error: {\"error\":{\"code\":\"invalid_parameter_error\",\ + \"message\":\"Range of input length should be [1, 98304]\"}}"; + assert!(is_context_window_overflow_message(body)); +} + +#[test] +fn context_overflow_ignores_other_dashscope_parameter_errors() { + // Same DashScope error envelope, but not the input-length range. + let body = "Provider returned error: {\"error\":{\"code\":\"invalid_parameter_error\",\ + \"message\":\"Range of temperature should be [0, 2)\"}}"; + assert!(!is_context_window_overflow_message(body)); +} + #[test] fn context_overflow_ignores_unrelated_and_rate_limit_bodies() { for body in [