can1357/oh-my-pi · error
vault:// URL requires a vault name or '_' for the active vau
Error message
vault:// URL requires a vault name or '_' for the active vault
What it means
A vault:// URL must name a vault (vault://<name>/...) or use "_" for the active vault. When the parsed VaultReference has neither — no vault component and not the active-vault form — resolveVaultRoot throws this error before consulting the vault directory. It is a strict URL-shape validation on the host portion of the URL.
Source
Thrown at packages/coding-agent/src/internal-urls/vault-protocol.ts:747
}
async #resolveVaultRoot(ref: VaultReference, context?: ResolveContext | WriteContext): Promise<string> {
const cached = getCachedVaultRoot(ref);
if (cached) return cached;
if (ref.active) {
const result = await this.#spawn(["vault", "info", "path"], context);
assertCliSuccess("vault info path", result);
const activePath = parseActiveVaultPath(result.stdout);
if (!activePath) {
throw new Error("vault:// active vault path was empty");
}
cachedActiveVaultPath = path.resolve(activePath);
return cachedActiveVaultPath;
}
if (!ref.vault) {
throw new Error("vault:// URL requires a vault name or '_' for the active vault");
}
const vaults = await this.#loadVaultDirectory(context);
const root = vaults.get(ref.vault);
if (!root) {
const available = Array.from(vaults.keys()).sort().join(", ") || "none";
throw new Error(`Unknown Obsidian vault: ${ref.vault}\nAvailable: ${available}`);
}
return path.resolve(root);
}
#vaultCliArg(ref: VaultReference): string[] {
return ref.forwardVault && ref.vault ? [`vault=${ref.vault}`] : [];
}
async #listVaults(
parsed: Extract<ParsedVaultUrl, { kind: "list-vaults" }>,
context?: ResolveContext,
): Promise<InternalResource> {View on GitHub (pinned to 9690622007)
Solutions
- Include a vault name in the URL host: vault://<vault-name>/path/to/file.md.
- Use the active-vault shorthand "_" if you mean the currently open vault: vault://_/path/to/file.md.
- Validate the URL with parseVaultUrl() before passing it to the handler.
Example fix
// before
const url = `vault://${vaultName}/note.md`; // vaultName was empty -> throws
// after
const url = vaultName ? `vault://${vaultName}/note.md` : "vault://_/note.md"; Defensive patterns
Strategy: validation
Validate before calling
const host = new URL(url.href).host; // or parse the vault segment
if (url.href.startsWith("vault://") && host !== "_" && host.length === 0) {
throw new Error("vault:// URL needs a vault name or '_' for the active vault");
} Type guard
function hasVaultComponent(href: string): boolean {
const m = /^vault:\/\/([^/]+)/.exec(href);
return !!m && m[1].length > 0;
} Try / catch
try {
return await resolveInternalUrl(url);
} catch (err) {
if (err instanceof Error && err.message.includes("requires a vault name or '_'") && activeVault) {
return resolveInternalUrl(url.replace("vault://", `vault://${activeVault}/`));
}
throw err;
} Prevention
- Construct vault URLs with a template that always includes the vault segment.
- Unit-test URL builders for empty vault-name inputs.
- Default to "vault://_/..." when no explicit vault is known.
When it happens
Trigger: Calling resolve/write with a malformed vault:// URL whose host/vault part is empty and not "_", e.g. "vault:///note.md" or "vault://" followed only by a path.
Common situations: String-built URLs where the vault segment was dropped by path-joining code; templates with an unfilled vault-name variable; trimming that consumed the vault segment.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- vault:// write only supports plain file paths
- 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/9f2035b18c0eaf68.
Report an issue: GitHub.