ruvnet/ruflo · error
Value exceeds maximum size of
Error message
Value exceeds maximum size of ${MAX_VALUE_SIZE} bytes What it means
memory_store rejects values larger than MAX_VALUE_SIZE: 1 MiB (1,048,576) measured as value.length on the string. validateMemoryInput throws before anything is persisted, protecting the hybrid memory backend (SQLite rows plus HNSW vector index) from being bloated by a single entry. There is no environment override — the ceiling is fixed in code.
Solutions
- Chunk the payload into multiple entries under a common key prefix (doc-1 ... doc-N) and reassemble on read
- Store a reference instead of the content: write the blob to disk or object storage, then memory_store its path/URL plus metadata
- Compress then encode (zlib deflate + base64) if the content is compressible — verify the result is still under 1 MiB
- Check value.length at the call site before invoking memory_store and fail fast with your own message
Example fix
// before
await mcp.callTool('memory_store', {
key: 'page-cache',
value: html, // 2.4MB scraped page -> Value exceeds maximum size of 1048576 bytes
});
// after
for (let i = 0; i < html.length; i += 512 * 1024) {
await mcp.callTool('memory_store', { key: `page-cache:${i / (512 * 1024)}`, value: html.slice(i, i + 512 * 1024) });
} Defensive patterns
Strategy: validation
Validate before calling
const MAX_VALUE_SIZE = 1024 * 1024;
function chunkedValues(value: string, chunkSize = 512 * 1024): Array<{ key: string; value: string }> {
if (value.length <= MAX_VALUE_SIZE) return [{ key: '0', value }];
const chunks: Array<{ key: string; value: string }> = [];
for (let i = 0; i < value.length; i += chunkSize) chunks.push({ key: String(i / chunkSize), value: value.slice(i, i + chunkSize) });
return chunks;
}
// for (const c of chunkedValues(blob)) await memoryStore({ key: `${baseKey}:${c.key}`, value: c.value }); Try / catch
try {
await memoryStore({ key, value });
} catch (e) {
if (e instanceof Error && e.message.includes('Value exceeds maximum size')) {
// split or externalize the payload, then retry — retrying identical input always fails
}
throw e;
} Prevention
- Check value.length against 1,048,576 before calling memory_store and fail fast in your own pipeline
- Store large blobs on disk/object storage and keep only references plus metadata in memory
- For append-style entries, cap growth: start a new suffixed entry instead of growing one forever
- Compress compressible payloads (zlib + base64) and verify the encoded size stays under the limit
When it happens
Trigger: memory_store whose value is a full JSON dump, base64 blob, log file, or concatenated report whose string length exceeds 1,048,576 characters; caching an entire HTTP response body or an LLM transcript in a single entry.
Common situations: Caching API responses or scraped pages into memory; pasting base64-encoded assets; append-style pipelines whose value grows until it crosses 1 MiB; migrating from a KV store that had no size limit.
Understand the failure class
Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.
Related errors
- Key exceeds maximum length of
- namespace exceeds 128 characters
- Query exceeds maximum length of
- Key contains disallowed characters
- label exceeds 256 chars
AI-assisted analysis of ruvnet/ruflo@9c61c86f06 (2026-08-18).
Data as JSON: /api/errors/e26ea06d29cce2d5.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts:76
}
// D-2: Input bounds for memory parameters
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.View on GitHub (pinned to 9c61c86f06)