can1357/oh-my-pi · error

Unable to initialize local:// root

Error message

Unable to initialize local:// root

What it means

resolveLocalTarget creates the session local root with mkdir(recursive) then calls fs.realpath on it. If realpath still fails with ENOENT — meaning the directory could not be created or vanished between mkdir and realpath (e.g. permissions, a race deleting it, tmpdir misconfiguration) — this opaque initialization error is thrown instead of a raw fs error.

Source

Thrown at packages/coding-agent/src/internal-urls/local-protocol.ts:353

	| { kind: "file"; path: string; size: number };

/**
 * Resolve a local:// URL to its on-disk target with realpath + containment
 * checks on the root, parent, and target so symlinks cannot escape the session
 * local root. Does NOT read or decode file contents — callers decide how to
 * consume the resolved path. Shared by {@link LocalProtocolHandler.resolve} and
 * {@link resolveLocalUrlToFile}.
 */
async function resolveLocalTarget(url: InternalUrl, opts: LocalProtocolOptions): Promise<ResolvedLocalTarget> {
	const localRoot = path.resolve(resolveLocalRoot(opts));
	await fs.mkdir(localRoot, { recursive: true });

	let resolvedRoot: string;
	try {
		resolvedRoot = await fs.realpath(localRoot);
	} catch (error) {
		if (isEnoent(error)) {
			throw new Error("Unable to initialize local:// root");
		}
		throw error;
	}

	const relativePath = extractRelativePath(url);
	const targetPath = relativePath ? path.resolve(resolvedRoot, relativePath) : resolvedRoot;
	ensureWithinRoot(targetPath, resolvedRoot);

	if (targetPath === resolvedRoot) {
		return { kind: "listing", root: resolvedRoot };
	}

	const parentDir = path.dirname(targetPath);
	try {
		const realParent = await fs.realpath(parentDir);
		ensureWithinRoot(realParent, resolvedRoot);
	} catch (error) {
		if (!isEnoent(error)) throw error;

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the session's artifacts directory and the local root under it exist and are writable; recreate the artifacts dir if deleted.
  2. Check TMPDIR (or os.tmpdir() target) is an existing writable directory when no artifacts dir is configured.
  3. Pass explicit localProtocolOptions with a getArtifactsDir that returns a valid directory to LocalProtocolHandler.setOverride or the resolve context.
Defensive patterns

Strategy: try-catch

Validate before calling

const root = resolveLocalRoot(options);
await fs.mkdir(root, { recursive: true }); // fail early with a clear fs error if the environment is broken

Try / catch

try { resource = await handler.resolve(url, ctx); } catch (e) { if (e.message === 'Unable to initialize local:// root') { /* check artifacts dir / TMPDIR writability, recreate session storage */ } else throw e; }

Prevention

When it happens

Trigger: Calling LocalProtocolHandler.resolve (or resolveLocalUrlToFile) when the artifacts dir's parent is unwritable so mkdir silently cannot create the path, or another process removed the freshly created root before realpath ran; TMPDIR pointing at a non-existent/unwritable location when no artifacts dir is configured.

Common situations: SDK embedding without a valid artifacts directory; sandboxed environments with read-only /tmp; sessions resumed after their artifacts directory was deleted externally.

Related errors


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