can1357/oh-my-pi · error
vault://${opLabel} failed: ${detail}
Error message
vault://${opLabel} failed: ${detail} What it means
`assertCliSuccess` wraps every Obsidian CLI subprocess invocation. If the spawned `obsidian` process exits non-zero, or exits 0 but printed a line starting with `Error:`, the CLI's own diagnostic (stderr, stdout, or the exit code) is surfaced as `vault://<op> failed: <detail>`. The error is a faithful pass-through of the Obsidian CLI failure, not a parser bug in this library.
Source
Thrown at packages/coding-agent/src/internal-urls/vault-protocol.ts:366
if (bin) return bin;
throw missingBinaryError();
}
function cliReportedError(result: ObsidianSpawnResult): string | undefined {
const stderr = result.stderr.trim();
if (stderr.startsWith("Error:")) return stderr;
const stdout = result.stdout.trim();
if (stdout.startsWith("Error:")) return stdout;
return undefined;
}
function assertCliSuccess(opLabel: string, result: ObsidianSpawnResult): void {
const reportedError = cliReportedError(result);
if (result.exitCode === 0 && !reportedError) return;
const stderr = result.stderr.trim();
const stdout = result.stdout.trim();
const detail = reportedError || stderr || stdout || `obsidian exited with code ${result.exitCode}`;
throw new Error(`vault://${opLabel} failed: ${detail}`);
}
function parseVaultDirectory(stdout: string): Map<string, string> {
const vaults = new Map<string, string>();
for (const line of stdout.split(/\r?\n/)) {
const trimmed = line.trimEnd();
if (!trimmed) continue;
const tab = trimmed.indexOf("\t");
if (tab <= 0) continue;
const name = trimmed.slice(0, tab);
const vaultPath = trimmed.slice(tab + 1).trim();
if (!name || !vaultPath) continue;
vaults.set(name, path.resolve(vaultPath));
}
return vaults;
}
function parseActiveVaultPath(stdout: string): string {View on GitHub (pinned to 9690622007)
Solutions
- Read the `detail` suffix — it is the Obsidian CLI's own error; fix the underlying cause it names.
- Run `vault://_/` (list vaults) and confirm the vault name in your URL matches an existing vault.
- Update the Obsidian app/CLI to a version supporting the subcommand (e.g. `base:query`, `search:context`).
- Enable the required core plugins (Daily notes for `daily`, Bases for `base`) and retry.
- If the CLI is transiently failing, retry the operation after confirming Obsidian is running.
Example fix
// before
const res = await handler.resolve(parseInternalUrl("vault://OldName/?op=daily"));
// vault://daily failed: vault "OldName" not found
// after: discover the actual vault name first
const vaults = await handler.resolve(parseInternalUrl("vault://_/"));
const res = await handler.resolve(parseInternalUrl(`vault://${encodeURIComponent(correctName)}/?op=daily`)); Defensive patterns
Strategy: retry
Validate before calling
// Before invoking, verify preconditions the CLI depends on:
const vaults = await handler.resolve(parseInternalUrl("vault://_/")); // throws a clear error if CLI/vaults unavailable
// confirm the vault name exists in vaults.textContent before targeting vault://<Name>/... Type guard
function isCliFailure(err: unknown): err is Error & { message: string } {
return err instanceof Error && /^vault:\/\/.+ failed: /.test(err.message);
} Try / catch
try {
const res = await handler.resolve(parseInternalUrl(url));
} catch (err) {
if (isCliFailure(err)) {
const detail = err.message.replace(/^vault:\/\/.+ failed: /, "");
logger.warn("obsidian cli failed", { url, detail });
// retry once for transient failures; otherwise surface `detail` to the user
} else throw err;
} Prevention
- Keep the Obsidian app and its CLI current — old CLIs reject newer subcommands
- Verify vault names with vault://_/ before referencing them
- Enable required core plugins (Daily notes, Bases) for daily/base ops
- Treat the message suffix as the authoritative diagnostic — it is the CLI's own stderr/stdout
When it happens
Trigger: #runCli / #loadVaultDirectory / #resolveVaultRoot / #vaultInfo spawn the Obsidian CLI and it fails: vault not found for the requested ref, daily-notes plugin not configured, Obsidian CLI too old and not accepting the subcommand, vault locked/unavailable, or the CLI prints `Error: ...` on stdout/stderr.
Common situations: Referencing a vault name that no longer exists or was renamed; Obsidian not running / CLI plugin version mismatch; daily notes core plugin disabled so `daily`/`daily-path` fail; transient Obsidian crashes or timeout kills (30s default) reported as a non-zero exit.
Related errors
- VHS failed to render the gallery screenshot${detail ? `: ${d
- Failed to build stats client (exit ${buildResult.exitCode})$
- --list-details, --exec, and --exec-batch are not supported b
- positional paths cannot be combined with --search-path
- unknown file type: {value}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/888c2182dc03a235.
Report an issue: GitHub.