Templater Error Handling

I have a Templater template for my Daily Notes that includes <% tp.user.weathernow() %> which is a user function that runs curl "wttr.in/Mequon?format=2". It has been working great for a couple weeks, but today wttr.in appears to be down, and the consequence is that Templater errors out, and I can’t create a daily note (note opens as blank with no content from the template).

Is there a way to make adding the weather (or anything else for that matter) fail more gracefully, like an if/then that says if error, just put “Weather Not Available”.

What is the code for the entire user function that grabs the weather?

You can also open the developer console to get a better idea what’s causing the problem by pressing Ctrl+Shift+i or Cmd+Shift+i

The curl command I listed is all it runs, it returns something like “:sunny: :thermometer:+21°F :wind_face::arrow_upper_right:13mph”. The site is back up, but I’m still wondering if Templater has any error handling capabilities in case this type of thing happens in the future. I did open the console, and I don’t recall the exact message, but it wasn’t much more useful than “the weather thing isn’t working”.

If you use a JavaScript execution command (<%* ... %> instead of <% ... %>), you can wrap your function in a try/catch, which will let you handle things gracefully the function if it errors out. Could you try something like this?

<%*
try {
  tp.user.weathernow()
} catch (e) {
  console.log(e)
}
%>

This way, things should behave as normal when they work. If the function fails, you should instead get the error logged to the console, but there will be no return and the rest of the template should work fine.

1 Like

This looks like what I was expecting to be possible, but I tried the code and it doesn’t return anything, even when <% tp.user.weathernow() %> by itself works. Is there another plugin I need beyond Templater to use JavaScript execution commands?

I didn’t test the function itself since I don’t have it implemented—only that the try/catch block works in Obsidian. I wonder if perhaps Settings -> Templater -> Enable User System Command Functions needs to be toggled on if it’s not already (though if it weren’t, I’d expect the function wouldn’t have run before)?

I do have that setting enabled. I hacked around a bit and finally got something to work:

<%* try { %><% tp.user.weathernow() %><%* } catch (e) { %>"Could not retrieve weather."<%* } %>

Seemed like the Javascript part wasn’t able to output, so I wrapped it around what I already had working and that seemed to do the trick. Thanks for pointing me in the right direction!

1 Like

When you switch to dynamic execution block, <%*, the output system changes, you need to append output to the tR variable.

You made it work since you went out of that block, and into a normal template block.

You could also have done:

<%*
try {
  tR = tp.user.weathernow()
} catch (e) {
  console.log(e)
}
%>
1 Like

I just tried that, but instead of getting the weather, everything in the template up to the end of that block was replaced with [object Promise] in the note.

Ok, my bad, you do need to await it, since it uses asynchronous functions.

So you’ll need something like tR = await tp.user.weathernow().

I added await to your suggested code bock and it seems to work, but everything before the code block in the template doesn’t show up in the note (everything after it does show up).

You would need to add any output to the tR variable in the entire dynamic execution code block. It’s part of the trade of to allow for arbitrary javascript to be run.

Gotcha, I’m very new to this environment. For now I’ll keep what I have working, but good to know for down the road when I eventually need to do something like that. Thanks!

1 Like

While I encourage you to experiment on your own and see what works, this is what has worked for me in the past.

Have an execution block at the very top of the note that does all the complicated calculations, querying, or inputs, the save all results in variables. Then, lower down, just output any of the variables you need.

Example:

---
tag: daily
---
<%*
let currentWeather

try {
  currentWeather = await tp.user.weathernow()
} catch (e) {
  console.log(e)
  currentWeather = "Cannot fetch Weather"
}

[Any other JS stuff]
_%>

[Rest of the template]

The weather is: <% currentWeather %>

You can make use of Templater’s Whitespace Control to help hide the Execution block.

Hope this helps!

3 Likes

Works like a charm. I really like this approach, makes sense for multiple reason. Thanks for sharing!

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