ruvnet/ruflo · error
namespace must be a non-empty string
Error message
namespace must be a non-empty string
What it means
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.
Source
Thrown at v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts:705
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.',
category: 'memory',
inputSchema: {
type: 'object',
properties: {
namespace: { type: 'string', description: 'Filter by namespace' },
limit: { type: 'number', description: 'Maximum results (default: 50)' },
offset: { type: 'number', description: 'Offset for pagination (default: 0)' },
},
},
handler: async (input) => {
await ensureInitialized();
const { listEntries } = await getMemoryFunctions();
const namespace = input.namespace as string | undefined;
const limit = (input.limit as number) || 50;
const offset = (input.offset as number) || 0;
if (namespace) { const vNs = validateIdentifier(namespace, 'namespace'); if (!vNs.valid) throw new Error(vNs.error); }
try {
const result = await listEntries({
namespace,
limit,
offset,
});
const entries = result.entries.map(e => ({
key: e.key,
namespace: e.namespace,
storedAt: e.createdAt,
updatedAt: e.updatedAt,
accessCount: e.accessCount,
hasEmbedding: e.hasEmbedding,
size: e.size,
}));
View on GitHub (pinned to fa13ee4ad6)
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
Example fix
// before
await mcp.callTool('memory_list', { namespace: 123 }); // number -> namespace must be a non-empty string
// after
await mcp.callTool('memory_list', { namespace: 'patterns' }); Defensive patterns
Strategy: type-guard
Validate before calling
// memory_list only skips validation for falsy namespace; ensure you pass string|undefined.
const ns = typeof args.namespace === 'string' && args.namespace.length > 0 ? args.namespace : undefined;
await mcp.callTool('memory_list', ns ? { namespace: ns } : {}); Type guard
function isNamespaceArg(v: unknown): v is string | undefined {
return v === undefined || (typeof v === 'string' && v.length > 0);
}
// if (!isNamespaceArg(args.namespace)) throw new TypeError('namespace must be a non-empty string or omitted'); Try / catch
try {
await memoryList({ namespace: args.namespace });
} catch (e) {
if (e instanceof Error && e.message === 'namespace must be a non-empty string') {
// caller sent a non-string JSON value — coerce or reject at your boundary, then retry
}
throw e;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.
Related errors
- namespace exceeds 128 characters
- namespace contains disallowed characters
- namespace contains path traversal
- namespace contains invalid characters (allowed: alphanumeric
- Namespace contains disallowed characters
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/2125c8a7ba0898a1.
Report an issue: GitHub.