{"record":{"id":"9f2035b18c0eaf68","repo":"can1357/oh-my-pi","slug":"vault-url-requires-a-vault-name-or-for-the","errorCode":null,"errorMessage":"vault:// URL requires a vault name or '_' for the active vault","messagePattern":"vault:// URL requires a vault name or '_' for the active vault","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/internal-urls/vault-protocol.ts","lineNumber":747,"sourceCode":"\t}\n\n\tasync #resolveVaultRoot(ref: VaultReference, context?: ResolveContext | WriteContext): Promise<string> {\n\t\tconst cached = getCachedVaultRoot(ref);\n\t\tif (cached) return cached;\n\n\t\tif (ref.active) {\n\t\t\tconst result = await this.#spawn([\"vault\", \"info\", \"path\"], context);\n\t\t\tassertCliSuccess(\"vault info path\", result);\n\t\t\tconst activePath = parseActiveVaultPath(result.stdout);\n\t\t\tif (!activePath) {\n\t\t\t\tthrow new Error(\"vault:// active vault path was empty\");\n\t\t\t}\n\t\t\tcachedActiveVaultPath = path.resolve(activePath);\n\t\t\treturn cachedActiveVaultPath;\n\t\t}\n\n\t\tif (!ref.vault) {\n\t\t\tthrow new Error(\"vault:// URL requires a vault name or '_' for the active vault\");\n\t\t}\n\t\tconst vaults = await this.#loadVaultDirectory(context);\n\t\tconst root = vaults.get(ref.vault);\n\t\tif (!root) {\n\t\t\tconst available = Array.from(vaults.keys()).sort().join(\", \") || \"none\";\n\t\t\tthrow new Error(`Unknown Obsidian vault: ${ref.vault}\\nAvailable: ${available}`);\n\t\t}\n\t\treturn path.resolve(root);\n\t}\n\n\t#vaultCliArg(ref: VaultReference): string[] {\n\t\treturn ref.forwardVault && ref.vault ? [`vault=${ref.vault}`] : [];\n\t}\n\n\tasync #listVaults(\n\t\tparsed: Extract<ParsedVaultUrl, { kind: \"list-vaults\" }>,\n\t\tcontext?: ResolveContext,\n\t): Promise<InternalResource> {","sourceCodeStart":729,"sourceCodeEnd":765,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/internal-urls/vault-protocol.ts#L729-L765","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst url = `vault://${vaultName}/note.md`; // vaultName was empty -> throws\n// after\nconst url = vaultName ? `vault://${vaultName}/note.md` : \"vault://_/note.md\";","handlingStrategy":"validation","validationCode":"const host = new URL(url.href).host; // or parse the vault segment\nif (url.href.startsWith(\"vault://\") && host !== \"_\" && host.length === 0) {\n  throw new Error(\"vault:// URL needs a vault name or '_' for the active vault\");\n}","typeGuard":"function hasVaultComponent(href: string): boolean {\n  const m = /^vault:\\/\\/([^/]+)/.exec(href);\n  return !!m && m[1].length > 0;\n}","tryCatchPattern":"try {\n  return await resolveInternalUrl(url);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"requires a vault name or '_'\") && activeVault) {\n    return resolveInternalUrl(url.replace(\"vault://\", `vault://${activeVault}/`));\n  }\n  throw err;\n}","preventionTips":["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."],"tags":["vault","url-validation","input-validation"],"backgroundTag":"invalid-url-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}