can1357/oh-my-pi · error

vault:// path resolution requires a cached vault root; read

Error message

vault:// path resolution requires a cached vault root; read vault:// first or use the write tool

What it means

resolveVaultUrlToPath needs the vault root's absolute path, which it takes from an in-process cache populated when a vault:// URL is actually read/listed (or via test hooks). If no vault has been accessed yet in this process — so getCachedVaultRoot returns nothing for the reference — the resolver throws this error telling you to read vault:// first. It is a warm-up requirement, not a permission problem.

Source

Thrown at packages/coding-agent/src/internal-urls/vault-protocol.ts:432

		} catch (error) {
			if (!isEnoent(error)) throw error;
			const parent = path.dirname(current);
			if (parent === current) throw error;
			current = parent;
		}
	}
}

export function resolveVaultUrlToPath(input: string | InternalUrl): string {
	if (!isVaultEnabled()) throw new VaultDisabledError();
	const parsed = parseVaultUrl(input);
	if (parsed.kind !== "fs-file" && parsed.kind !== "fs-dir") {
		throw new Error("vault:// path resolution only supports plain filesystem paths");
	}

	const cachedRoot = getCachedVaultRoot(parsed.ref);
	if (!cachedRoot) {
		throw new Error(
			"vault:// path resolution requires a cached vault root; read vault:// first or use the write tool",
		);
	}

	const resolvedRoot = fs.realpathSync(cachedRoot);
	const targetPath = parsed.relativePath ? path.resolve(resolvedRoot, parsed.relativePath) : resolvedRoot;
	ensureWithinRoot(targetPath, resolvedRoot);

	try {
		const realTarget = fs.realpathSync(targetPath);
		ensureWithinRoot(realTarget, resolvedRoot);
	} catch (error) {
		if (!isEnoent(error)) throw error;
		const realParent = findExistingAncestorSync(path.dirname(targetPath), resolvedRoot);
		ensureWithinRoot(realParent, resolvedRoot);
	}

	return targetPath;

View on GitHub (pinned to 9690622007)

Solutions

  1. Read `vault://_/` (or the specific vault dir) once first to populate the cache, then call resolveVaultUrlToPath.
  2. Use the active-vault form `vault://_/path` if the active vault's root is already cached (cachedActiveVaultPath).
  3. In tests, seed the cache via VaultProtocolHandler.setActiveVaultPathForTests() or setVaultDirectoryForTests().
  4. If the vault name is wrong (never cached), list vaults via handler.resolve(vault://_/) and use an existing name.

Example fix

// before
const p = resolveVaultUrlToPath("vault://MyVault/notes/a.md"); // no cache yet
// after
await handler.resolve(parseInternalUrl("vault://_/")); // warms vault directory cache
const p = resolveVaultUrlToPath("vault://MyVault/notes/a.md"); // now resolves
Defensive patterns

Strategy: fallback

Validate before calling

// ensure a vault has been touched this process before path resolution:
await handler.resolve(parseInternalUrl("vault://_/")); // lists vaults, populates cache
const p = resolveVaultUrlToPath(url);

Type guard

function isColdCacheError(err: unknown): boolean {
  return err instanceof Error &&
    err.message.includes("requires a cached vault root");
}

Try / catch

try {
  return resolveVaultUrlToPath(url);
} catch (err) {
  if (isColdCacheError(err)) {
    await handler.resolve(parseInternalUrl("vault://_/")); // warm the cache
    return resolveVaultUrlToPath(url); // retry once
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling resolveVaultUrlToPath as the very first vault operation in a fresh process (e.g. resolving `vault://MyVault/notes/a.md` without ever listing vaults or reading any vault:// URL), or referencing a named vault whose root was never cached while only the active vault was.

Common situations: SDK/tooling that resolves a vault link to a path before reading; multi-vault setups where the target vault name differs from the one previously accessed; tests that forgot setActiveVaultPathForTests/setVaultDirectoryForTests.

Related errors


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