ruvnet/ruflo · error
Namespace contains disallowed characters
Error message
Namespace contains disallowed characters
What it means
The same DANGEROUS_KEY_PATTERN guard applied to keys is applied to the namespace argument in validateMemoryInput (memory-tools.ts:86): namespaces containing ; & | ` $ ( ) { } [ ] < > ! # \ NUL or ../ / ..\ are rejected with 'Namespace contains disallowed characters' (#1425). This is the write-side check only — memory_list/cleanup/export run the stricter shared validateIdentifier, so a namespace that passes here (e.g. one with spaces) can still fail those tools later.
Solutions
- Use a plain identifier namespace — alphanumeric plus _, -, ., : — which satisfies both this check and the stricter list/cleanup/export validator
- Sanitize with the same replacement the library applies to keys (dangerous characters → '_')
- Never build namespaces with '../' segments; use a flat naming scheme
- Keep the namespace under 128 characters so the stricter validator's length cap also passes
Example fix
// before
await mcp.callTool('memory_store', { key: 'auth', value, namespace: 'patterns#v2' }); // Namespace contains disallowed characters
// after
await mcp.callTool('memory_store', { key: 'auth', value, namespace: 'patterns-v2' }); Defensive patterns
Strategy: validation
Validate before calling
// Use one canonical namespace policy that satisfies BOTH validators:
// write-side DANGEROUS_KEY_CHARS and the stricter read-side IDENTIFIER_RE.
const IDENTIFIER_RE = /^[a-zA-Z0-9_][a-zA-Z0-9_\-.:]{0,127}$/;
function safeNamespace(ns: string): string | undefined {
const clean = ns.replace(/[^A-Za-z0-9_\-.:]+/g, '-').replace(/^[^A-Za-z0-9_]+/, '');
return IDENTIFIER_RE.test(clean) ? clean : undefined; // undefined = list all namespaces
} Try / catch
try {
await memoryStore({ key, value, namespace });
} catch (e) {
if (e instanceof Error && e.message.includes('Namespace contains disallowed characters')) {
// sanitize namespace and retry once with the allowlist replacement
}
throw e;
} Prevention
- Restrict namespaces to alphanumerics plus _, -, ., : from day one — it satisfies every memory tool, not just the store path
- Never build namespaces from unexpanded shell variables or pasted markdown
- Watch the asymmetry: memory_store tolerates characters (spaces) that memory_list/cleanup/export reject
- Validate namespaces at configuration load time, not at call time, so bad values fail loudly and early
When it happens
Trigger: memory_store with namespace 'patterns#auth', 'team(a)', 'a$b', 'ns|prod', or 'data/../prod'. Note ':' and spaces pass this write-side check but spaces fail the list-side validator, producing the store/list asymmetry.
Common situations: Namespaces built from user or org names, folder paths, or tags that carry punctuation; unexpanded shell variables ('$name') copied from examples; shared root cause with key rejection — both checks use the same character set constant.
Related errors
- Key contains disallowed characters
- namespace contains disallowed characters
- memory path contains disallowed characters
- namespace contains invalid characters (allowed…
- namespace contains path traversal
AI-assisted analysis of ruvnet/ruflo@9c61c86f06 (2026-08-18).
Data as JSON: /api/errors/0c79a5818b6bebee.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/mcp-tools/memory-tools.ts:86
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;
}
// #1937 — minimal glob → RegExp helper for memory_import_claude exclusion
// patterns. Anchored. Supports the three operators the issue's voice-fidelity
// workflow needs:
// `**` — any chars including path separators
// `*` — any chars except path separatorsView on GitHub (pinned to 9c61c86f06)