can1357/oh-my-pi · error
memory:// URL requires a namespace: memory://root or memory:
Error message
memory:// URL requires a namespace: memory://root or memory://<memory-id>
What it means
With a memory backend active, the host portion of a memory:// URL is the namespace: 'root' for the file-backed memory summary, or a mnemopi memory id. A URL with no host at all (e.g. 'memory://' or 'memory:///path') has nothing to resolve, so resolve throws and tells the caller the two accepted URL forms.
Source
Thrown at packages/coding-agent/src/internal-urls/memory-protocol.ts:299
/**
* Protocol handler for memory:// URLs.
* Resolves file-backed roots against the calling session cwd when provided.
* Contextless callers fall back to the live-session registry for legacy
* cross-session lookups.
*/
export class MemoryProtocolHandler implements ProtocolHandler {
readonly scheme = "memory";
readonly immutable = true;
async resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource> {
const backend = memoryBackendFromContext(context);
if (backend === "off") {
throw new Error("Unknown protocol: memory://");
}
const namespace = url.rawHost || url.hostname;
if (!namespace) {
throw new Error("memory:// URL requires a namespace: memory://root or memory://<memory-id>");
}
// Mnemopi rows live in SQLite banks per session, keyed by memory id.
// Any host other than the file-backed `root` namespace is treated as a
// mnemopi memory id lookup. This is the read counterpart to
// `memory_edit update` and lets agents inspect the full content of a
// clipped recall preview before overwriting it (issue #4443).
if (namespace !== MEMORY_NAMESPACE) {
const mnemopiStates = mnemopiSessionStatesFromRegistry();
const hindsightActive =
backend === "hindsight" ||
(mnemopiStates.length === 0 &&
AgentRegistry.global()
.list()
.some(ref => ref.session?.getHindsightSessionState?.()));
if (hindsightActive) {
// Hindsight keeps memories server-side and exposes no
// `memory://<id>` addressing, yet the shared `recall` toolView on GitHub (pinned to 9690622007)
Solutions
- Read the project memory summary with 'memory://root'.
- Read a stored mnemopi memory by id with 'memory://<memory-id>' using an id listed by recall.
- Fix the URL builder/prompt so the namespace is always interpolated and non-empty.
Example fix
// before
read("memory://")
// after
read("memory://root") Defensive patterns
Strategy: validation
Validate before calling
const ns = url.rawHost || url.hostname;
if (!ns) throw new Error(`Use memory://root or memory://<memory-id>, got: ${url.href}`); Type guard
function hasNamespace(url: InternalUrl): boolean {
return Boolean(url.rawHost || url.hostname);
} Try / catch
try {
return await handler.resolve(url, ctx);
} catch (err) {
if (err instanceof Error && err.message.includes("requires a namespace")) {
return await handler.resolve(parseInternalUrl("memory://root"), ctx);
}
throw err;
} Prevention
- Always include a host: memory://root for the summary, memory://<id> for mnemopi rows.
- Validate interpolated id variables are non-empty before building the URL.
- Surface valid forms to agents via the handler's completion output.
When it happens
Trigger: Calling MemoryProtocolHandler.resolve with an InternalUrl whose rawHost/hostname are empty — 'memory://', 'memory:///' — from a read tool call or programmatic URL construction that omitted the namespace.
Common situations: Agents emitting 'read memory://' after truncation; template strings where the id variable was empty; users typing memory:// in a path prompt without the 'root' host.
Related errors
- memory:// URL requires a namespace: memory://root
- Provider delete URL must not embed an account credential
- ${destination} returned an invalid upload URL
- Destination option endpoint must be an absolute URL
- Destination option endpoint must use HTTP or HTTPS
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/68b52ffaad1e74cb.
Report an issue: GitHub.