Summary
In Obsidian 1.12.7, frontmatter aliases are correctly parsed and surfaced by autocomplete (getLinkSuggestions), but the wikilink resolver (getFirstLinkpathDest / getLinkpathDest) does not consult them. Clicking [[<alias>]] creates a new note instead of resolving to the file that declares the alias.
A targeted code-level inspection of app.metadataCache shows there is no code path in the running app that adds aliases to uniqueFileLookup, which is the only data source the resolver reads.
Steps to reproduce
-
Create a note
Resources/general/illusion-of-knowledge.mdwith frontmatter:--- aliases: - the illusion of knowledge - the knowledge illusion --- -
In any other note, type
[[the illusion of knowledge]]. -
Click the link.
Expected result
The link resolves to Resources/general/illusion-of-knowledge.md.
Actual result
The link is treated as unresolved. Clicking it creates a new file named the illusion of knowledge.md.
Environment
- Obsidian: 1.12.7 (installer 1.12.7)
- OS: macOS (Darwin 25.3.0)
- Vault id:
09ee4dc563a703ee - Vault stored on Dropbox-synced folder (case-insensitive HFS+/APFS).
- Reproduces in restricted mode (community plugins disabled), per testing.
- Reproduces after a full
IndexedDB/cache wipe and clean rebuild. - Reproduces on multiple files independently — vault-wide, not file-specific.
Community plugins enabled at time of report: calendar, dataview, homepage, obsidian-icon-folder, obsidian-outliner, obsidian-tasks-plugin, open-vscode, periodic-notes, quickadd, templater-obsidian. (Issue persists with all disabled.)
Diagnostic evidence
The following can be reproduced via Settings → Community plugins → “Open with developer tools” → Console.
1. Aliases are correctly parsed and visible to autocomplete
app.metadataCache.getCache('Resources/general/illusion-of-knowledge.md').frontmatter.aliases
// → ["the illusion of knowledge", "the knowledge illusion"]
app.metadataCache.getLinkSuggestions().filter(s => s.alias?.includes('illusion'))
// → returns objects with the file and each alias (autocomplete works)
2. The resolver returns null for aliases
app.metadataCache.getFirstLinkpathDest('the illusion of knowledge', '')
// → null
app.metadataCache.getFirstLinkpathDest('illusion-of-knowledge', '')
// → TFile (filename works)
3. uniqueFileLookup (the resolver’s only index) has no alias entries vault-wide
const u = app.metadataCache.uniqueFileLookup.data;
const keys = Array.from(u.keys());
keys.length;
// → 2873 (matches file count)
keys.filter(k => k === 'the illusion of knowledge.md');
// → []
Across the whole vault (18 files with aliases in frontmatter, 20 aliases total), zero are present in uniqueFileLookup.
4. The resolver source has no alias branch
String(app.metadataCache.getLinkpathDest).includes('alias')
// → false
The decompiled resolver:
function (e, t) {
if (e === '' && t && (f = this.vault.getAbstractFileByPath(t)) instanceof TFile) return [f];
var n = e.toLowerCase(), i = nu(n), r = null;
if (i.contains('.')) r = this.uniqueFileLookup.get(i);
if (!r) { i = nu(n = (e + '.md').toLowerCase()); r = this.uniqueFileLookup.get(i); }
if (!r) return [];
// ... path matching only
}
Only consults uniqueFileLookup. Never reads frontmatter.aliases.
5. The metadata-cache parser does not register aliases
computeFileMetadataAsync only adds the filename:
this.uniqueFileLookup.add(e.name.toLowerCase(), e); // filename only
A walk of the entire app object tree finds three callers of uniqueFileLookup.add: initialize, computeFileMetadataAsync, onRename. None of them add aliases. Searching for any function whose source contains both uniqueFileLookup and alias returns zero results.
6. Instrumented re-parse confirms zero alias add calls
const u = app.metadataCache.uniqueFileLookup;
const orig = u.add.bind(u);
const log = [];
u.add = (k, f) => { log.push({k, f: f.path}); return orig(k, f); };
const f = app.vault.getAbstractFileByPath('Resources/general/illusion-of-knowledge.md');
await app.metadataCache.computeMetadataAsync(f);
// log shows zero entries for any alias key — only the filename gets added
Workaround
A small plugin that listens to metadataCache.on('changed'), reads frontmatter.aliases, and adds each alias as (alias + '.md').toLowerCase() to uniqueFileLookup.data makes resolution work correctly. The fix takes ~30 lines of code, suggesting the missing registration in the core is a small omission.
Question for triage
Is the resolver supposed to consult uniqueFileLookup for alias entries (and the parser is missing the registration), or is there a separate alias index that’s supposed to be created elsewhere? Either way, in this build the data path is absent.