can1357/oh-my-pi · error

Unknown protocol: memory://

Error message

Unknown protocol: memory://

What it means

MemoryProtocolHandler.resolve first checks the configured memory.backend. If it is set to 'off', memory support is disabled entirely, so the handler reports the memory:// scheme itself as unknown — the same error a URL router would give for an unregistered protocol. This is intentional: with memories off, no memory:// URL can resolve.

Source

Thrown at packages/coding-agent/src/internal-urls/memory-protocol.ts:295

		size: Buffer.byteLength(content, "utf-8"),
		notes: [],
	};
}

/**
 * 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()

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-enable memory support by setting memory.backend to a supported value (e.g. 'file' or 'mnemopi') in settings.
  2. If memory should stay off, stop issuing memory:// reads — gate the caller/agent tool on memory being enabled.
  3. Check that the ResolveContext carries the right settings object; a wrong context can surface an unintended 'off' backend.

Example fix

// settings.json — before
{ "memory": { "backend": "off" } }
// after
{ "memory": { "backend": "file" } }
Defensive patterns

Strategy: validation

Validate before calling

const backend = settings.get("memory.backend");
if (backend === "off") throw new Error("memory:// reads require an enabled memory backend");

Try / catch

try {
  return await handler.resolve(url, ctx);
} catch (err) {
  if (err instanceof Error && err.message === "Unknown protocol: memory://") {
    // memory disabled — skip or prompt user to enable memory.backend
  } else throw err;
}

Prevention

When it happens

Trigger: Resolving any memory:// URL while context.settings.get('memory.backend') === 'off' — i.e. memories explicitly disabled in settings — reaches this branch before any namespace parsing.

Common situations: User disabled memory in omp settings but an agent prompt or recall tool description still references memory:// URLs; a plugin or extension hard-coding memory:// reads in an environment where the backend was turned off.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/0c97348271332a91. Report an issue: GitHub.