can1357/oh-my-pi · error
Invalid URL encoding in memory:// path: ${url.href}
Error message
Invalid URL encoding in memory:// path: ${url.href} What it means
After stripping the leading slash, the memory:// pathname is percent-decoded with decodeURIComponent. If the escapes are malformed (e.g. a dangling '%' or a truncated '%E4' sequence), decoding throws and the resolver rethrows this error naming the offending URL, rather than producing a corrupted path.
Source
Thrown at packages/coding-agent/src/internal-urls/memory-protocol.ts:135
export function resolveMemoryUrlToPath(url: InternalUrl, memoryRoot: string): string {
const namespace = url.rawHost || url.hostname;
if (!namespace) {
throw new Error("memory:// URL requires a namespace: memory://root");
}
if (namespace !== MEMORY_NAMESPACE) {
throw new Error(`Unknown memory namespace: ${namespace}. Supported: ${MEMORY_NAMESPACE}`);
}
const rawPathname = url.rawPathname ?? url.pathname;
const hasPath = rawPathname && rawPathname !== "/" && rawPathname !== "";
if (!hasPath) {
return path.resolve(memoryRoot, DEFAULT_MEMORY_FILE);
}
let relativePath: string;
try {
relativePath = decodeURIComponent(rawPathname.slice(1));
} catch {
throw new Error(`Invalid URL encoding in memory:// path: ${url.href}`);
}
try {
validateRelativePath(relativePath);
} catch (error) {
throw toMemoryValidationError(error);
}
return path.resolve(memoryRoot, relativePath);
}
async function tryResolveInRoot(url: InternalUrl, memoryRoot: string): Promise<InternalResource | undefined> {
const resolved = path.resolve(memoryRoot);
let resolvedRoot: string;
try {
resolvedRoot = await fs.realpath(resolved);
} catch (error) {
if (isEnoent(error)) return undefined;View on GitHub (pinned to 9690622007)
Solutions
- Percent-encode special characters properly: encode '%' as %25 and non-ASCII as valid UTF-8 escapes before putting them in the URL.
- Use encodeURIComponent on dynamic path segments when building memory:// URLs programmatically.
- If the '%' is meant literally in a filename, escape it as %25, e.g. memory://root/100%25done.md.
Example fix
// before
read(`memory://root/${rawName}`) // rawName = "50% off.md"
// after
read(`memory://root/${encodeURIComponent(rawName)}`) Defensive patterns
Strategy: validation
Validate before calling
const pathname = url.rawPathname ?? url.pathname;
try { decodeURIComponent(pathname.slice(1)); } catch { throw new Error(`Invalid percent-encoding: ${url.href}`); } Try / catch
try {
const p = resolveMemoryUrlToPath(url, root);
} catch (err) {
if (err instanceof Error && err.message.startsWith("Invalid URL encoding")) {
// re-encode the path segment and retry once
} else throw err;
} Prevention
- encodeURIComponent every dynamic path segment before composing memory:// URLs.
- Escape literal '%' in filenames as %25.
- Never paste URLs through shells that strip or mangle '%'.
When it happens
Trigger: resolveMemoryUrlToPath receiving a pathname with invalid percent-encoding, such as memory://root/notes%.md or memory://root/%E4%B8 (truncated UTF-8 escape), usually from hand-written or shell-mangled URLs.
Common situations: Copy-pasting a URL where a '%' got eaten by a shell; double-encoding mistakes (writing %2520 then partially decoding); tools that interpolate raw strings containing '%' into the path.
Related errors
- memory:// URL requires a namespace: memory://root
- Unknown memory namespace: ${namespace}. Supported: ${MEMORY_
- memory:// URL requires a namespace: memory://root or memory:
- ssh:// does not support URL query strings; percent-encode a
- ssh:// does not support URL fragments; percent-encode a lite
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/eb530b54d1cc2ca1.
Report an issue: GitHub.