How it works
How it works
Section titled âHow it worksâThe behavior NameGuard prevents
Section titled âThe behavior NameGuard preventsâObsidianâs New link format setting has three values: Shortest path when possible, Relative path to file, and Absolute path in vault.
In shortest mode, a link like [[Foobar]] is stored with just the note name as long as that name
is unique. Internally, when Obsidian renders a link target it asks whether the short name still
resolves to exactly one file. If it does, the short form is kept. If it does not, Obsidian falls back
to a longer, disambiguated path.
So the instant a second Foobar appears anywhere in the vault, every existing [[Foobar]] becomes
ambiguous. To keep those links pointing at the original file, Obsidian rewrites them:
[[Foobar]][[notes/Foobar]]This rewrite is driven by Obsidianâs link-update engine, which runs after a create or rename:
- It snapshots where every link currently resolves.
- It performs the file operation (the new/renamed file appears).
- It compares the new resolution against the snapshot and rewrites any link whose target would have changed, using the disambiguated path.
In relative and absolute mode this rewrite does not happen, because links are already stored with a path and adding another same-named note does not change how they resolve. That is why the problem â and NameGuard â only matters in shortest mode by default.
What NameGuard does
Section titled âWhat NameGuard doesâThe cleanest way to prevent the rewrite is to prevent the duplicate from ever existing. NameGuard wraps the vault methods that all file creation and movement funnel through:
Vault.createandVault.createBinaryâ used by new notes, âcreate note from linkâ, templates, and most programmatic creation.Vault.renameâ used by moving and renaming, includingFileManager.renameFile, which callsVault.renameinternally.
Before delegating to the original method, each wrapper asks a small, pure decision function whether the operation would introduce a duplicate name. If it would, the wrapper returns a rejected promise (and shows a notice), so the underlying create/rename never runs and the link-update engine has nothing to rewrite.
The decision logic lives in src/uniqueness.ts and is fully unit-tested in isolation. The wiring that
connects it to Obsidian lives in src/name-guard.ts.
How a collision is detected
Section titled âHow a collision is detectedâTo check whether a name already exists, NameGuard reuses Obsidianâs own resolver,
MetadataCache.getFirstLinkpathDest(name, ""). At the moment a guard runs, the new file is not yet
indexed, so a non-null result always means a pre-existing file with that name. When âMarkdown
notes onlyâ is turned off, NameGuard additionally scans loaded files by base name to cover non-markdown
types.
Why pre-existing duplicates are left alone
Section titled âWhy pre-existing duplicates are left aloneâNameGuard never inspects or âfixesâ duplicates that already exist; it only evaluates the new name being introduced by the current operation. If two notes were already named the same before you installed NameGuard, they keep working exactly as before. This is deliberate: NameGuard is a guard on new operations, not a vault linter.
Scope and limitations
Section titled âScope and limitationsâ- Vault API only. Files that appear through external means â a sync client writing to disk, an
external editor, or the OS file system â are discovered by Obsidianâs file watcher rather than
created through
Vault.create, so NameGuard cannot intercept them. - Name, not full path. Uniqueness is enforced on the note name (no folder, no extension), which is exactly the unit that shortest-format links care about.