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
- Verify the session's artifacts directory and the local root under it exist and are writable; recreate the artifacts dir if deleted.
- Check TMPDIR (or os.tmpdir() target) is an existing writable directory when no artifacts dir is configured.
- 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
- Ensure the session artifacts directory exists and is writable at session startup.
- Verify TMPDIR points at an existing writable directory in sandboxed/CI environments.
- Pass explicit localProtocolOptions via setOverride or context when embedding the SDK.
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
- cannot stat {file}: {error}
- File not found: ${path}
- File not found: ${path}
- File not found: ${inputPath}
- Marketplace catalog not found at ${tried.map(p => `"${p}"`).
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/48331847c6fa69f4.
Report an issue: GitHub.