can1357/oh-my-pi · error

Invalid URL encoding in memory:// path: ${input}

Error message

Invalid URL encoding in memory:// path: ${input}

What it means

After stripping the leading slash, the raw pathname is percent-decoded with decodeURIComponent. Malformed escape sequences (e.g. a stray '%' not followed by two hex digits, or truncated multibyte sequences) make decodeURIComponent throw a URIError, which is rethrown with this message naming the original input.

Source

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

	// Parse only the scheme and authority. A literal `?` in the path is glob
	// syntax, not a query delimiter, and must survive unchanged.
	const url = parseInternalUrl(urlMatch[1]);
	const namespace = url.rawHost || url.hostname;
	if (url.protocol !== "memory:" || namespace !== MEMORY_NAMESPACE) {
		throw new Error(`Memory glob patterns require the ${MEMORY_NAMESPACE} namespace: ${input}`);
	}

	const rawPathname = urlMatch[2] ?? "";
	if (/%(?:2f|5c)/i.test(rawPathname)) {
		throw new Error(`Encoded path separators are not allowed in memory:// glob patterns: ${input}`);
	}

	let relativePath: string;
	try {
		relativePath = decodeURIComponent(rawPathname.replace(/^\//, ""));
	} catch {
		throw new Error(`Invalid URL encoding in memory:// path: ${input}`);
	}

	try {
		validateRelativePath(relativePath);
	} catch (error) {
		throw toMemoryValidationError(error);
	}

	const rawSegments = rawPathname.replace(/^\//, "").split("/");
	const firstGlobIndex = rawSegments.findIndex(segment => ["*", "?", "[", "{"].some(char => segment.includes(char)));
	if (firstGlobIndex === -1) {
		throw new Error(`memory:// URL does not contain a glob pattern: ${input}`);
	}

	const rawBasePath = rawSegments.slice(0, firstGlobIndex).join("/") || ".";
	return {
		baseUrl: `memory://${namespace}/${rawBasePath}`,
		globPattern: rawSegments.slice(firstGlobIndex).map(decodeGlobSuffixSegment).join("/"),

View on GitHub (pinned to 9690622007)

Solutions

  1. Encode literal '%' characters in the path as %25 (e.g. 50%25.md) and retry.
  2. Check the full URL for truncated or typo'd escape sequences (%zz, single %, incomplete UTF-8 runs) and repair them.
  3. When building URLs programmatically, always percent-encode with encodeURIComponent rather than concatenating raw strings containing '%'.

Example fix

// before
splitMemoryGlobPattern("memory://root/reports/50%.md"); // bare % breaks decode
// after
splitMemoryGlobPattern("memory://root/reports/50%25.md");
Defensive patterns

Strategy: validation

Validate before calling

function isDecodablePath(rawPathname: string): boolean {
  try {
    decodeURIComponent(rawPathname.replace(/^\//, ""));
    return true;
  } catch {
    return false;
  }
}

Try / catch

try {
  return splitMemoryGlobPattern(input);
} catch (e) {
  if (e instanceof Error && e.message.startsWith("Invalid URL encoding in memory:// path")) {
    const repaired = input.replace(/%(?![0-9a-f]{2})/gi, "%25"); // escape bare %
    return splitMemoryGlobPattern(repaired);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling splitMemoryGlobPattern (via memoryGlob) with a memory:// URL whose path contains invalid percent-encoding such as memory://root/notes/50%.md or %zz, or a cut-off escape like %e2%80 at the end.

Common situations: Users pasting URLs where a literal '%' (common in file names like '100%_done.md') was never encoded as %25; truncation by a log/UI that clipped the URL; double-encoding pipelines mangling escapes.

Related errors


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