{"record":{"id":"2125c8a7ba0898a1","repo":"ruvnet/ruflo","slug":"namespace-must-be-a-non-empty-string","errorCode":null,"errorMessage":"namespace must be a non-empty string","messagePattern":"namespace must be a non-empty string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts","lineNumber":705,"sourceCode":"    description: 'Enumerate stored memory entries (optionally filtered by namespace/tags) without semantic search. Use when native Glob is wrong because the entries are not files (they live in .swarm/memory.db). For inspection / audit / \"what is in my memory\" — pair with memory_search for retrieval-by-meaning.',\n    category: 'memory',\n    inputSchema: {\n      type: 'object',\n      properties: {\n        namespace: { type: 'string', description: 'Filter by namespace' },\n        limit: { type: 'number', description: 'Maximum results (default: 50)' },\n        offset: { type: 'number', description: 'Offset for pagination (default: 0)' },\n      },\n    },\n    handler: async (input) => {\n      await ensureInitialized();\n      const { listEntries } = await getMemoryFunctions();\n\n      const namespace = input.namespace as string | undefined;\n      const limit = (input.limit as number) || 50;\n      const offset = (input.offset as number) || 0;\n\n      if (namespace) { const vNs = validateIdentifier(namespace, 'namespace'); if (!vNs.valid) throw new Error(vNs.error); }\n\n      try {\n        const result = await listEntries({\n          namespace,\n          limit,\n          offset,\n        });\n\n        const entries = result.entries.map(e => ({\n          key: e.key,\n          namespace: e.namespace,\n          storedAt: e.createdAt,\n          updatedAt: e.updatedAt,\n          accessCount: e.accessCount,\n          hasEmbedding: e.hasEmbedding,\n          size: e.size,\n        }));\n","sourceCodeStart":687,"sourceCodeEnd":723,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts#L687-L723","documentation":"memory_list validates its optional namespace with the shared validateIdentifier (from cli-core validate-input.ts, wired in at memory-tools.ts:705) and throws the validator's message on failure. This variant fires when the value is truthy but not a non-empty string: the handler only casts (`input.namespace as string | undefined`), so a JSON number, array, or object reaches the validator as-is and fails the typeof check. The check runs only when namespace is truthy, so omitting it (or passing '') lists across all namespaces without error.","triggerScenarios":"Calling memory_list with { \"namespace\": 5 }, { \"namespace\": [\"patterns\"] }, or { \"namespace\": { \"name\": \"patterns\" } } — MCP JSON arguments are not coerced to the declared string type, so any non-string truthy JSON value produces exactly this message.","commonSituations":"LLM-generated tool arguments using the wrong JSON type; programmatic callers passing a numeric ID or enum where the namespace name was expected; configuration defaults that produce numbers.","solutions":["Pass the namespace as a JSON string: { namespace: 'patterns' }","Omit the namespace field entirely when you want entries from all namespaces","Coerce at the call site: namespace: cfg.namespace == null ? undefined : String(cfg.namespace)","Type the caller's request payload as { namespace?: string } so compile-time or schema validation catches it earlier"],"exampleFix":"// before\nawait mcp.callTool('memory_list', { namespace: 123 }); // number -> namespace must be a non-empty string\n\n// after\nawait mcp.callTool('memory_list', { namespace: 'patterns' });","handlingStrategy":"type-guard","validationCode":"// memory_list only skips validation for falsy namespace; ensure you pass string|undefined.\nconst ns = typeof args.namespace === 'string' && args.namespace.length > 0 ? args.namespace : undefined;\nawait mcp.callTool('memory_list', ns ? { namespace: ns } : {});","typeGuard":"function isNamespaceArg(v: unknown): v is string | undefined {\n  return v === undefined || (typeof v === 'string' && v.length > 0);\n}\n// if (!isNamespaceArg(args.namespace)) throw new TypeError('namespace must be a non-empty string or omitted');","tryCatchPattern":"try {\n  await memoryList({ namespace: args.namespace });\n} catch (e) {\n  if (e instanceof Error && e.message === 'namespace must be a non-empty string') {\n    // caller sent a non-string JSON value — coerce or reject at your boundary, then retry\n  }\n  throw e;\n}","preventionTips":["Type the request payload as { namespace?: string } and validate with a schema before invoking MCP tools","Coerce optional numerics/enums with String(...) at the call site","Remember omitting namespace lists all namespaces — do not pass 0/null/[] as 'no filter'","Log the raw JSON arguments when a tool call fails so type mistakes are obvious"],"tags":["memory","mcp","list","type-validation","namespace"],"backgroundTag":"wrong-argument-type","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}