Is it possible to find all files in vault with bad YAML?

What I’m trying to do

I’ve noticed that sometimes plugins which operate on properties fail to operate on files because they have bad YAML formatting. When this happens, it’s not obvious that this is the cause of the problem. Made me wonder, is there a way to quickly find all files in my vault that have such errors? Maybe through a quick javascript command, or with dataview?
Obsidian displays the YAML of such files in red, so I know Obsidian is aware of this.
Here is an example I recently encountered in my vault. In this case the Author: property is improperly formatted.

Things I have tried

I’ve looked through the community plugins and haven’t seen anything that can do this. I would be willing to use a command line tool. I’m running MacOS and Obsidian Version 1.5.8 (Installer 1.4.13)
Thanks for any help.

In the community plugins, I see “Linter”, an addon aimed to maintain consistency in note formatting. It also “formats” YAML tags, so perhaps will be useful to identify and even correct wrongly formatted YAML headers.

1 Like

This kind of intrigued me a little bit, so after looking through what’s available in the app.metadataCache it seems that the frontmatter* entries are missing when the yaml is bad, but there is still an entry in sections for the yaml section. This we can then utilise to detect where our YAML is bad. I also found in some cases that the frontmatter could contain a notvalid setting, without anything else.


const result = []

for (let [fname, fcache] of Object.entries( {
  // fname is the filename
  // fcache is the entry from metadataCache.fileCache
  // mcache is the actual metadataCache.metadataCache entry
  const mcache =[fcache.hash]
  if ( (mcache && !mcache.frontmatter &&
        mcache.hasOwnProperty("sections") &&
        mcache["sections"].some(s => s.type == "yaml"))
     || ( mcache && mcache.frontmatter && mcache.frontmatter.notvalid ) 
     ) {
    const yamlIndex = mcache["sections"].findIndex(s => s.type == "yaml")
    let yamlStart, yamlEnd
    // Pull out start and end, if section is found
    if ( yamlIndex !== -1 ) {
      yamlStart = mcache["sections"][yamlIndex]?.position.start.line
      yamlEnd = mcache["sections"][yamlIndex]?.position.end.line
    // Determine the cause of the faulty frontmatter
    let cause
    if ( mcache.frontmatter?.notvalid )        cause = "Not valid"
    else if ( yamlIndex == -1 )                cause = "NO yaml"
    else if ( yamlStart == 0 && yamlEnd == 1 ) cause = "Empty"
    else cause = "Bad"
    result.push([dv.fileLink(fname), cause, yamlStart ?? "", yamlEnd ?? ""])
    // console.log(fname, " » ", mcache) 
  //console.log(fname, " » ", fcache, "\n  »» ", mcache)

dv.table(["File", "Yaml status", "Start", "End"], result)

This query seems to do the trick to detect either bad or empty yaml. If you don’t want to see the empty yaml’s, then just remove else { ... } part from the query. I’m assuming in this query that the yamlStart is always 0.

If you want to see all available information, you could uncomment the last console.log() line, and open up your Developer Tools in the Console pane. But it can be a lot of information depending on the size of your vault… So be forewarned on that aspect.

On my test vault this query resulted in this display:

Some comments on this result:

  • “Not valid” came when I had some empty lines in front of the yaml
  • “Empty” is when the two first lines are the fences
  • “Bad” is all the rest… You’ll need to visually inspect all of those to determine why they are bad

To determine bad yaml I suggest moving the code fence up towards the middle, and see if it gets valid or not when switching to a rendering view. And then keeping moving the fence (or possibly the top part) around to determine in which section, and finally which line is bad.


Thanks, I actually have linter installed but it does not do what I want. Appreciate the comment.


  • Thank you
    I can work with this! And it is instructive as to how to deal with Obsidian’s guts.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.