ruvnet/ruflo · error
Query exceeds maximum length of
Error message
Query exceeds maximum length of ${MAX_QUERY_LENGTH} characters What it means
memory_search (and any path feeding a query through validateMemoryInput) throws when the query exceeds MAX_QUERY_LENGTH (4096 characters). The bound keeps the semantic-search embedding input bounded and stops callers smuggling whole prompts through the query field. It is a pre-flight check — no index is touched when it fails.
Solutions
- Reduce the query to the distinctive keywords or one descriptive sentence — the backend is semantic, so short queries retrieve better
- Search with the most informative snippet (e.g. the exception line from a stack trace, ~100-300 chars) rather than the whole log
- If you must match long content, store it first via memory_store and search with a short summary query
- Guard at the call site: reject or truncate query.slice(0, 4096) before invoking the tool
Example fix
// before
await mcp.callTool('memory_search', { query: fullStackTrace }); // 12k chars -> Query exceeds maximum length
// after
const q = fullStackTrace.split('\n').find(l => l.startsWith('Error')) ?? fullStackTrace.slice(0, 200);
await mcp.callTool('memory_search', { query: q }); Defensive patterns
Strategy: validation
Validate before calling
const MAX_QUERY_LENGTH = 4096;
function prepareSearchQuery(raw: string): string {
if (raw.length <= MAX_QUERY_LENGTH) return raw;
// semantic search works best with distinctive terms: take the head or the first 'Error' line of a log
return raw.slice(0, MAX_QUERY_LENGTH);
}
// const query = prepareSearchQuery(userInput); Try / catch
try {
await memorySearch({ query });
} catch (e) {
if (e instanceof Error && e.message.includes('Query exceeds maximum length')) {
// shorten to keywords/snippet and retry once with the compact query
}
throw e;
} Prevention
- Never pass whole documents, transcripts, or stack traces as the search query — extract 1-3 distinctive phrases
- Cap query length at the call site (4096 chars) and log when truncation happens so it is visible
- For long-content matching, store the content first and search with a short summary
- Remember the backend is semantic: shorter, well-chosen queries retrieve better than long dumps
When it happens
Trigger: memory_search with a query containing an entire document, stack trace, or chat transcript instead of a short phrase; concatenating 'context + question' strings for RAG until they pass 4096 characters.
Common situations: Pasting a full error log into the search query expecting keyword matching; building retrieval queries by string concatenation; agents passing the complete user message as the query.
Related errors
- Key exceeds maximum length of
- namespace exceeds 128 characters
- Value exceeds maximum size of
- Key contains disallowed characters
- label exceeds 256 chars
AI-assisted analysis of ruvnet/ruflo@9c61c86f06 (2026-08-18).
Data as JSON: /api/errors/ebef3408d7f86680.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts:79
const MAX_KEY_LENGTH = 1024;
const MAX_VALUE_SIZE = 1024 * 1024; // 1MB
const MAX_QUERY_LENGTH = 4096;
// #1425 — single source of truth for the dangerous-character set rejected by
// validateMemoryInput. Imported by sanitizeMemoryKey so write-side sanitization
// and read-side rejection can never drift apart (the symmetry bug behind #1884).
const DANGEROUS_KEY_CHARS = /[;&|`$(){}[\]<>!#\\\0]|\.\.[/\\]/g;
const DANGEROUS_KEY_PATTERN = /[;&|`$(){}[\]<>!#\\\0]|\.\.[/\\]/;
function validateMemoryInput(key?: string, value?: string, query?: string, namespace?: string): void {
if (key && key.length > MAX_KEY_LENGTH) {
throw new Error(`Key exceeds maximum length of ${MAX_KEY_LENGTH} characters`);
}
if (value && value.length > MAX_VALUE_SIZE) {
throw new Error(`Value exceeds maximum size of ${MAX_VALUE_SIZE} bytes`);
}
if (query && query.length > MAX_QUERY_LENGTH) {
throw new Error(`Query exceeds maximum length of ${MAX_QUERY_LENGTH} characters`);
}
// Reject path traversal and shell metacharacters in keys/namespaces (#1425)
if (key && DANGEROUS_KEY_PATTERN.test(key)) {
throw new Error('Key contains disallowed characters');
}
if (namespace && DANGEROUS_KEY_PATTERN.test(namespace)) {
throw new Error('Namespace contains disallowed characters');
}
}
// #1884 — sanitize a key produced from arbitrary input (markdown headings,
// frontmatter names, file names) so it survives validateMemoryInput on the
// read/delete path. Replaces every dangerous char with `_`. Truncates to
// MAX_KEY_LENGTH so the bound check in validateMemoryInput also passes.
// Keep this in sync with DANGEROUS_KEY_PATTERN — they share DANGEROUS_KEY_CHARS.
function sanitizeMemoryKey(key: string): string {
const safe = key.replace(DANGEROUS_KEY_CHARS, '_');
return safe.length > MAX_KEY_LENGTH ? safe.slice(0, MAX_KEY_LENGTH) : safe;View on GitHub (pinned to 9c61c86f06)