can1357/oh-my-pi · error
Unsupported vault:// file op: ${rawOp}
Error message
Unsupported vault:// file op: ${rawOp} What it means
When a vault:// URL includes a file path plus an `op` query parameter, `parseVaultOp` only accepts the whitelisted file operations (outline, backlinks, links, tags, properties, tasks, wordcount, history, base). Any other `op` value with a path present is rejected with this error. The whitelist is intentional: file ops map one-to-one to Obsidian CLI subcommands.
Source
Thrown at packages/coding-agent/src/internal-urls/vault-protocol.ts:197
function makeVaultReference(host: string): VaultReference {
if (!host || host === "_") {
return { vault: null, active: true, forwardVault: false, display: "_" };
}
return { vault: host, active: false, forwardVault: true, display: host };
}
function isFileOp(rawOp: string): rawOp is FileOp {
return FILE_OPS[rawOp as FileOp] === true;
}
function isVaultOp(rawOp: string): rawOp is VaultOp {
return VAULT_OPS[rawOp as VaultOp] === true;
}
function parseVaultOp(rawOp: string, hasFilePath: boolean): FileOp | VaultOp {
if (hasFilePath) {
if (!isFileOp(rawOp)) {
throw new Error(`Unsupported vault:// file op: ${rawOp}`);
}
return rawOp;
}
if (!isVaultOp(rawOp)) {
throw new Error(`Unsupported vault:// vault op: ${rawOp}`);
}
return rawOp;
}
export function parseVaultUrl(input: string | InternalUrl): ParsedVaultUrl {
const url = typeof input === "string" ? parseInternalUrl(input) : input;
const host = url.rawHost || url.hostname;
const params = paramsFromUrl(url);
const rawOp = typeof params.op === "string" ? params.op : undefined;
const { rawPathname, relativePath, hasPath, isDirectory } = decodeVaultPath(url);
if (!host && !hasPath && !rawOp) {
return { kind: "list-vaults", url: url.href, params };View on GitHub (pinned to 9690622007)
Solutions
- Use one of the supported file ops: outline, backlinks, links, tags, properties, tasks, wordcount, history, base.
- If you intended a vault-wide op (search, daily, orphans, unresolved, deadends, bases, bookmarks, recents, templates, aliases, property), remove the file path from the URL.
- Fix casing/typos — op matching is exact and case-sensitive.
- If the op genuinely exists in the Obsidian CLI, add it to FILE_OPS in vault-protocol.ts.
Example fix
// before const url = "vault://_/notes/idea.md?op=search&q=test"; // search is not a file op // after const url = "vault://_/?op=search&q=test"; // vault-wide search, no path // or per-file: const url2 = "vault://_/notes/idea.md?op=backlinks";
Defensive patterns
Strategy: validation
Validate before calling
const FILE_OPS = ["outline","backlinks","links","tags","properties","tasks","wordcount","history","base"];
function isValidFileOp(op: string): boolean { return FILE_OPS.includes(op); }
// check isValidFileOp(op) before appending ?op= to a path-bearing vault:// URL Type guard
function isFileOpOp(op: string): op is "outline"|"backlinks"|"links"|"tags"|"properties"|"tasks"|"wordcount"|"history"|"base" {
return ["outline","backlinks","links","tags","properties","tasks","wordcount","history","base"].includes(op);
} Try / catch
try {
const res = await handler.resolve(parseInternalUrl(url));
} catch (err) {
if (err instanceof Error && err.message.startsWith("Unsupported vault:// file op:")) {
// fall back to reading the file itself or a supported op
} else throw err;
} Prevention
- Keep a shared constant list of valid file ops and build URLs from it
- Remember ops are case-sensitive: use lowercase exactly as documented
- Vault-wide ops (search, daily, ...) are not file ops — drop the path or switch ops
- Check the Obsidian CLI version before using newly added ops
When it happens
Trigger: `vault://_/notes/foo.md?op=summarize`, `?op=search` (search is a vault op, not a file op), `?op=Outline` (case-sensitive), or a typo like `?op=backlink` while the URL has a non-empty path.
Common situations: Assuming every vault op also works per-file (e.g. `search` with a path); typos or wrong casing in generated URLs; using an op added in a newer Obsidian CLI version that this handler does not yet whitelist.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Unsupported vault:// vault op: ${rawOp}
- vault:// path resolution only supports plain filesystem path
- vault://${op} requires '${name}' query parameter
- Provider delete URL must not embed an account credential
- Gemini Files API delete requires a valid file name
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f0481afb4556259d.
Report an issue: GitHub.