Tp.file.path(true) wrong in startup templates with multiple new notes

Description:

I’m using a startup template <% tp.user.execute_templates(tp) %>to (re)create multiple Obsidian notes at once, each containing this template:

<%* tp.user.add_index_frontmatter(tp, tp.file.find_tfile(tp.file.path(true))) %>

This function manipulates the note’s frontmatter (adds tags, index, etc.).

function executeTemplates(tp) {
  const filesToProcess = ...; // Pre-filtered list of notes to process
  const vault = tp.app.vault;

  for (const file of filesToProcess) {
    console.log("Processing:", file.path);

    const originalContent = await vault.read(file);
    const newContent = originalContent; // May modify content if needed
    const newFileName = file.basename;
    const newPath = file.path.replace(file.basename, newFileName);

    // Delete original file and recreate it
    await vault.delete(file);
    await vault.create(newPath, newContent);
    ...
  }
}
function addIndexTag(tp, file) {
    const title = tp.file.title;
    const fileFromTp = tp.file.find_tfile(tp.file.path(true));
    const sanitizedTitle = tp.user.sanitize_string(title);
    console.log("Sanitized Title:", sanitizedTitle);
    console.log("Path: ", tp.file.path(true));
    console.log("This is the file:", file);
    console.log("This ist the fileFromTp", fileFromTp);
    ....

Log output:


Problem:

When multiple notes are created simultaneously, tp.file.title is correct per note — but tp.file.path(true) is the same across all notes, pointing to the wrong file. As a result, the frontmatter is applied to the wrong file or overwritten.


What I’m trying to do

  • I want to safely run frontmatter manipulation on multiple newly created notes (via startup templates)
  • I need a reliable way to reference the correct file in each template, even when multiple templates run in parallel|

Things I have tried

  • This issue happens even if I capture tp.file.path(true) inside the template itself
  • It seems tp.file.title uses the render context, but tp.file.path(true) uses the global active file and gets overwritten when templates run in parallel

I’m not fully grasping your setup and connection between the various templates, but aren’t you supposed to use tp.file.create_new() to create new files? And if using that, do that resolve some of your issue(s)?

At least, it seems like a cleaner way of mimicking how Templater would normally create new files.

You’re right — I should’ve been more explicit about my setup and goal.

I’m creating notes using the Raycast Obsidian extension, which writes the Templater syntax <%* tp.user.add_index_frontmatter(tp, tp.file.find_tfile(tp.file.path(true))) %> directly into the body of each new note.

However, since these notes are often created while the vault is closed, the embedded template isn’t executed on creation (enabled). To avoid needing to keep Obsidian open all the time, I’m trying to find a way to execute these templates after the fact — ideally when the vault is next opened.

To do this, I’ve experimented with a startup template that scans for these newly created notes (tagged #unprocessed) and recreates them to simulate a file creation event — which then re-triggers Templater execution. It’s a bit of a workaround, and so far, it’s only partially reliable — especially when multiple notes are processed in parallel, where context and frontmatter handling get tricky.

My end goal: reliably execute embedded Templater logic in notes created when Obsidian is closed — without needing to visit and execute each note manually.

Happy to clarify more if needed — and I’m definitely open to cleaner solutions!

I’m not understanding the reasoning why you do this as you do it, for starters I see a reference to vault.read() with a comment on possibly needing to change the file. There is a reason why vault.process() exists, and that is for that atomic change on a file. It would be a safer option. And then it could do all of the changes since it’s meant for that kind of handling.

I neither understand why you delay the creation of the frontmatter when you’re outside of Obsidian anyhow. Why not then just create what’s needed when you’re creating the file?

It also seems convoluted to do a find file on the file which should have been set already. If it’s set, it shouldn’t be needed, and if not set, then what is it looking for?

There is also a command to execute templates within a file, but I’m not sure if that requires that the file is open already within the editor.

Lastly, you should seriously consider to implement some limiting in case you’ve created many files, so that not too many notes are processed in parallell. It could be wise to actually limit your processing to just one or a few, and do the changes one after another. Especially if the changes somehow can cause links to be renamed, caches to be updated/changed with related information which might or might not be corrected when some of the other stuff is completed.

In short, I really think you need to reconsider what you’re doing, as it seems rather unsafe to proceed on the path you’ve so far described.

1 Like

Hi again, and thank you so much for your invaluable advice. You helped untangle several misunderstandings on my part—vault.process() turned out to be exactly the solution I needed. On top of that, you inspired me to tweak the Raycast extension for Obsidian even further, allowing me to completely forgo Templater. Now, creation, metadata manipulation, and file movements are all handled seamlessly through the extension.