can1357/oh-my-pi · error

vault:// URL must resolve to a file or directory: ${parsed.u

Error message

vault:// URL must resolve to a file or directory: ${parsed.url}

What it means

In the file-read path, after realpath and the directory branch, the handler requires stat.isFile(). Anything that is neither a directory nor a regular file — FIFOs, sockets, devices, etc. — triggers this error with the original URL. It is a defensive check so the handler never reads non-regular filesystem objects through vault://.

Source

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

			if (!isEnoent(error)) throw error;
		}

		let realTargetPath: string;
		try {
			realTargetPath = await fs.promises.realpath(targetPath);
		} catch (error) {
			if (isEnoent(error)) {
				throw new Error(`Vault file not found: ${parsed.url}`);
			}
			throw error;
		}
		ensureWithinRoot(realTargetPath, root);
		const stat = await fs.promises.stat(realTargetPath);
		if (stat.isDirectory()) {
			return this.#listDir(parsed, context);
		}
		if (!stat.isFile()) {
			throw new Error(`vault:// URL must resolve to a file or directory: ${parsed.url}`);
		}

		const content = await Bun.file(realTargetPath).text();
		return {
			url: parsed.url,
			content,
			contentType: getContentType(realTargetPath),
			size: Buffer.byteLength(content, "utf-8"),
			sourcePath: realTargetPath,
		};
	}

	async #writeFile(
		parsed: Extract<ParsedVaultUrl, { kind: "fs-file" }>,
		content: string,
		context?: WriteContext,
	): Promise<void> {
		const { root, targetPath } = await this.#resolveFsTarget(parsed, context);

View on GitHub (pinned to 9690622007)

Solutions

  1. Point the URL at a regular file or directory instead of the special file.
  2. Remove or relocate the symlink/special file from the vault if it was created accidentally.
  3. If you must access such a target, read it through a filesystem API outside vault://.

Example fix

// before
await resolveInternalUrl("vault://_/ipc.sock"); // special file -> throws
// after
await resolveInternalUrl("vault://_/ipc-config.md"); // regular file
Defensive patterns

Strategy: type-guard

Validate before calling

import * as fs from "node:fs/promises";
const stat = await fs.stat(targetPath);
if (!stat.isFile() && !stat.isDirectory()) {
  throw new Error(`${targetPath} is a special file; vault:// only reads regular files/directories`);
}

Type guard

function isRegularOrDir(stat: fs.Stats): boolean {
  return stat.isFile() || stat.isDirectory();
}

Try / catch

try {
  return await resolveInternalUrl(url);
} catch (err) {
  if (err instanceof Error && err.message.includes("must resolve to a file or directory")) {
    // skip this target; it is a socket/FIFO/device inside the vault
    return null;
  }
  throw err;
}

Prevention

When it happens

Trigger: Resolving a vault:// URL whose target realpath is a special file (socket, FIFO, device node) rather than a regular file or directory, e.g. a symlink inside the vault pointing at a Unix socket.

Common situations: Vaults containing unexpected symlink targets into /tmp or /dev; stray special files created by other tooling inside the vault directory.

Related errors


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