tauri-apps/tauri · error
Failed to setup handlebar template
Error message
Failed to setup handlebar template
What it means
During the WiX MSI build, tauri-bundler registers the main.wxs Handlebars template. When a custom template path is configured, the template string is compiled with register_template_string; if Handlebars fails to parse/compile it, the crate panics via .expect("Failed to setup handlebar template") (the custom-template branch panics with "Failed to setup custom handlebar template"). This aborts bundling immediately because an unparseable template means no installer can be generated.
Solutions
- Open the custom .wxs template and fix the Handlebars syntax error (check every {{#if}}/{{#each}} has a matching closing tag).
- Test the template against the built-in one: temporarily remove bundle.windows.wix.template from tauri.conf.json to confirm the stock template builds.
- Update your custom template to match the current tauri-bundler main.wxs (copy from the tauri-bundler version you use and re-apply your edits).
- Verify the template file is valid UTF-8 and not truncated.
Example fix
// before (tauri.conf.json)
"wix": { "template": "installer/main.wxs" } // template has unclosed {{#if}}
// after
// fix installer/main.wxs:
// {{#if product_version}} ... {{/if}} <- ensure every block is closed Defensive patterns
Strategy: validation
Validate before calling
// validate custom wix template before bundling
let tpl = std::fs::read_to_string("installer/main.wxs")?;
handlebars::Handlebars::new().register_template_string("main.wxs", tpl)
.map_err(|e| anyhow!("invalid wix template: {}", e))?; Type guard
fn is_valid_template(h: &handlebars::Handlebars, name: &str, src: &str) -> bool {
h.register_template_string(name, src).is_ok()
} Try / catch
// in Rust the panic aborts the process; run bundling in a subprocess and surface stderr, // or pre-validate the template as above before calling bundle_project.
Prevention
- Re-derive custom templates from the main.wxs of your exact tauri-bundler version after every upgrade
- Lint Handlebars blocks ({{#if}}/{{#each}} closings) before committing the template
- Keep template edits small and test a full bundle build in CI
When it happens
Trigger: Calling bundle_project with bundle.windows.wix.template set to a custom .wxs file whose content fails Handlebars compilation (malformed Handlebars syntax such as unclosed {{#if}} blocks, bad helper usage, or invalid characters). The map_err to String then expect turns the compile error into a panic.
Common situations: Users copy an old main.wxs from a previous tauri version into their Tauri config; template variables/helpers changed between tauri-bundler releases, so the custom template no longer compiles. Also hand-edited templates with mismatched {{/each}} or {{#if}} tags, or a template saved with the wrong encoding.
Related errors
- Failed to setup custom handlebar template
- app version build number cannot be greater than 65535
- app version major number cannot be greater than 255
- app version minor number cannot be greater than 255
- app version patch number cannot be greater than 65535
AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18).
Data as JSON: /api/errors/be67ded5a564f493.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tauri-bundler/src/bundle/windows/msi/mod.rs:747
let schemes = protocols
.iter()
.flat_map(|p| &p.schemes)
.collect::<Vec<_>>();
if !schemes.is_empty() {
data.insert("deep_link_protocols", to_json(schemes));
}
}
if let Some(path) = custom_template_path {
handlebars
.register_template_string("main.wxs", fs::read_to_string(path)?)
.map_err(|e| e.to_string())
.expect("Failed to setup custom handlebar template");
} else {
handlebars
.register_template_string("main.wxs", include_str!("./main.wxs"))
.map_err(|e| e.to_string())
.expect("Failed to setup handlebar template");
}
if enable_elevated_update_task {
data.insert(
"msiexec_args",
to_json(
settings
.updater()
.map(|updater| updater.msiexec_args)
.map(|args| args.join(" "))
.unwrap_or_else(|| "/passive".to_string()),
),
);
// Create the update task XML
let skip_uac_task = Handlebars::new();
let xml = include_str!("./update-task.xml");
let update_content = skip_uac_task.render_template(xml, &data)?;View on GitHub (pinned to 460ec35447)