can1357/oh-my-pi · error
vault:// write only supports plain file paths
Error message
vault:// write only supports plain file paths
What it means
After the enabled check, VaultProtocolHandler.write() parses the URL with parseVaultUrl() and requires the result to have kind "fs-file" — i.e. a plain filesystem path inside a vault. Other parsed kinds (directory or CLI-backed references like attachments) are rejected because writing arbitrary content only makes sense for plain file paths. This is an input-validation error, not a state error.
Source
Thrown at packages/coding-agent/src/internal-urls/vault-protocol.ts:713
case "list-vaults":
return this.#listVaults(parsed, context);
case "vault-info":
return this.#vaultInfo(parsed, context);
case "fs-dir":
return this.#listDir(parsed, context);
case "fs-file":
return this.#readFile(parsed, context);
case "file-op":
case "vault-op":
return this.#runCli(parsed, context);
}
}
async write(url: InternalUrl, content: string, context?: WriteContext): Promise<void> {
if (!isVaultEnabled()) throw new VaultDisabledError();
const parsed = parseVaultUrl(url);
if (parsed.kind !== "fs-file") {
throw new Error("vault:// write only supports plain file paths");
}
await this.#writeFile(parsed, content, context);
}
async #spawn(args: string[], context?: ResolveContext | WriteContext): Promise<ObsidianSpawnResult> {
const bin = requireObsidianBinary(this.#resolveObsidianBinary);
return this.#spawnObsidian(bin, args, context?.signal, DEFAULT_OBSIDIAN_TIMEOUT_MS);
}
async #loadVaultDirectory(context?: ResolveContext | WriteContext): Promise<Map<string, string>> {
if (cachedVaultDirectory) return cachedVaultDirectory;
const result = await this.#spawn(["vaults", "verbose"], context);
assertCliSuccess("vaults", result);
cachedVaultDirectory = parseVaultDirectory(result.stdout);
return cachedVaultDirectory;
}
async #resolveVaultRoot(ref: VaultReference, context?: ResolveContext | WriteContext): Promise<string> {View on GitHub (pinned to 9690622007)
Solutions
- Pass a plain file path in the vault:// URL (e.g. vault://<vault>/path/to/note.md), not a directory or CLI resource.
- Check the parsed kind with parseVaultUrl() before calling write, and route directory targets to other operations (e.g. resolve for listing).
- Create/choose a concrete file name if you intended to write into a directory.
Example fix
// before
await handler.write(parseInternalUrl("vault://_/notes/"), text); // directory -> throws
// after
await handler.write(parseInternalUrl("vault://_/notes/todo.md"), text); Defensive patterns
Strategy: validation
Validate before calling
const parsed = parseVaultUrl(url);
if (parsed.kind !== "fs-file") {
throw new Error(`vault:// write needs a plain file path, got kind=${parsed.kind}`);
} Type guard
function isFsFileKind(parsed: ReturnType<typeof parseVaultUrl>): parsed is Extract<ReturnType<typeof parseVaultUrl>, { kind: "fs-file" }> {
return parsed.kind === "fs-file";
} Try / catch
try {
await handler.write(url, content);
} catch (err) {
if (err instanceof Error && err.message === "vault:// write only supports plain file paths") {
// fix the URL to a plain file path and retry once
return;
}
throw err;
} Prevention
- Always end vault:// write URLs in a concrete file name.
- Validate parsed.kind before calling write; route other kinds to read/list operations.
- Avoid building write URLs from directory inputs.
When it happens
Trigger: Calling handler.write(url, content) with a vault:// URL that parses to a non-fs-file kind — e.g. a directory URL like vault://_/notes/ or a URL targeting a CLI-backed resource — instead of a plain file path like vault://_/notes/idea.md.
Common situations: Agents or scripts generating vault:// URLs programmatically and passing directory URLs to write; mistaking the directory-listing URL form for a writable file target.
Related errors
- vault:// URL requires a vault name or '_' for the active vau
- Invalid xd:// URL: ${url.href}. Use xd:// or xd://<tool>.
- err.to_string() (timestamp parse error)
- duration is too large: {value}
- invalid date: {value}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/78b288c91aba3b4c.
Report an issue: GitHub.