{"record":{"id":"e26ea06d29cce2d5","repo":"ruvnet/ruflo","slug":"value-exceeds-maximum-size-of-max-value-size-by","errorCode":null,"errorMessage":"Value exceeds maximum size of ${MAX_VALUE_SIZE} bytes","messagePattern":"Value exceeds maximum size of (.+?) bytes","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts","lineNumber":76,"sourceCode":"}\n\n// D-2: Input bounds for memory parameters\nconst MAX_KEY_LENGTH = 1024;\nconst MAX_VALUE_SIZE = 1024 * 1024; // 1MB\nconst MAX_QUERY_LENGTH = 4096;\n\n// #1425 — single source of truth for the dangerous-character set rejected by\n// validateMemoryInput. Imported by sanitizeMemoryKey so write-side sanitization\n// and read-side rejection can never drift apart (the symmetry bug behind #1884).\nconst DANGEROUS_KEY_CHARS = /[;&|`$(){}[\\]<>!#\\\\\\0]|\\.\\.[/\\\\]/g;\nconst DANGEROUS_KEY_PATTERN = /[;&|`$(){}[\\]<>!#\\\\\\0]|\\.\\.[/\\\\]/;\n\nfunction validateMemoryInput(key?: string, value?: string, query?: string, namespace?: string): void {\n  if (key && key.length > MAX_KEY_LENGTH) {\n    throw new Error(`Key exceeds maximum length of ${MAX_KEY_LENGTH} characters`);\n  }\n  if (value && value.length > MAX_VALUE_SIZE) {\n    throw new Error(`Value exceeds maximum size of ${MAX_VALUE_SIZE} bytes`);\n  }\n  if (query && query.length > MAX_QUERY_LENGTH) {\n    throw new Error(`Query exceeds maximum length of ${MAX_QUERY_LENGTH} characters`);\n  }\n  // Reject path traversal and shell metacharacters in keys/namespaces (#1425)\n  if (key && DANGEROUS_KEY_PATTERN.test(key)) {\n    throw new Error('Key contains disallowed characters');\n  }\n  if (namespace && DANGEROUS_KEY_PATTERN.test(namespace)) {\n    throw new Error('Namespace contains disallowed characters');\n  }\n}\n\n// #1884 — sanitize a key produced from arbitrary input (markdown headings,\n// frontmatter names, file names) so it survives validateMemoryInput on the\n// read/delete path. Replaces every dangerous char with `_`. Truncates to\n// MAX_KEY_LENGTH so the bound check in validateMemoryInput also passes.\n// Keep this in sync with DANGEROUS_KEY_PATTERN — they share DANGEROUS_KEY_CHARS.","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/ruvnet/ruflo/blob/9c61c86f06b439af2a95085ae9bb0ca839662e41/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait mcp.callTool('memory_store', {\n  key: 'page-cache',\n  value: html, // 2.4MB scraped page -> Value exceeds maximum size of 1048576 bytes\n});\n\n// after\nfor (let i = 0; i < html.length; i += 512 * 1024) {\n  await mcp.callTool('memory_store', { key: `page-cache:${i / (512 * 1024)}`, value: html.slice(i, i + 512 * 1024) });\n}","handlingStrategy":"validation","validationCode":"const MAX_VALUE_SIZE = 1024 * 1024;\nfunction chunkedValues(value: string, chunkSize = 512 * 1024): Array<{ key: string; value: string }> {\n  if (value.length <= MAX_VALUE_SIZE) return [{ key: '0', value }];\n  const chunks: Array<{ key: string; value: string }> = [];\n  for (let i = 0; i < value.length; i += chunkSize) chunks.push({ key: String(i / chunkSize), value: value.slice(i, i + chunkSize) });\n  return chunks;\n}\n// for (const c of chunkedValues(blob)) await memoryStore({ key: `${baseKey}:${c.key}`, value: c.value });","typeGuard":null,"tryCatchPattern":"try {\n  await memoryStore({ key, value });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Value exceeds maximum size')) {\n    // split or externalize the payload, then retry — retrying identical input always fails\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["memory","mcp","validation","limits","payload","size-limit"],"backgroundTag":"payload-too-large","analyzedSha":"9c61c86f06b439af2a95085ae9bb0ca839662e41","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}