stalwartlabs/stalwart · error

Failed to parse calendar template

Error message

Failed to parse calendar template

What it means

This panic occurs during GroupwareConfig construction when the embedded, minified calendar-alarm HTML template fails Template::parse. Because include_str! bakes resources/html-templates/calendar-alarm.html.min into the binary at compile time, the .expect() should never fire in normal operation; if it does, the shipped template content is corrupt or incompatible with the current Template parser.

Source

Thrown at crates/common/src/config/groupware.rs:133

            max_ical_size: calendar.max_i_calendar_size as usize,
            max_ical_instances: calendar.max_recurrence_expansions as usize,
            max_ical_attendees_per_instance: calendar.max_attendees as usize,
            max_vcard_size: book.max_v_card_size as usize,
            vcard_version: match book.v_card_version {
                RegistryVCardVersion::V3 => VCardVersion::V3_0,
                RegistryVCardVersion::V4 => VCardVersion::V4_0,
            },
            max_file_size: file.max_size as usize,
            alarms_enabled: alarm.enable,
            alarms_minimum_interval: alarm.min_trigger_interval.into_inner().as_secs() as i64,
            alarms_allow_external_recipients: alarm.allow_external_rcpts,
            alarms_from_name: alarm.from_name,
            alarms_from_email: alarm.from_email,
            alarms_template: Template::parse(include_str!(concat!(
                env!("CARGO_MANIFEST_DIR"),
                "/../../resources/html-templates/calendar-alarm.html.min"
            )))
            .expect("Failed to parse calendar template"),
            itip_enabled: sched.enable,
            itip_auto_add: sched.auto_add_invitations,
            itip_inbound_max_ical_size: sched.itip_max_size as usize,
            itip_outbound_max_recipients: sched.max_recipients as usize,
            itip_inbox_auto_expunge: dr
                .expunge_scheduling_inbox_after
                .map(|d| d.into_inner().as_secs()),
            itip_http_rsvp_url: if sched.http_rsvp_enable {
                if let Some(url) = sched
                    .http_rsvp_url
                    .as_deref()
                    .map(|v| v.trim().trim_end_matches('/'))
                    .filter(|v| !v.is_empty())
                {
                    Some(url.to_string())
                } else {
                    Some(format!("https://{}/calendar/rsvp", system.default_hostname))
                }

View on GitHub (pinned to e962003857)

Solutions

  1. Restore the pristine resources/html-templates/calendar-alarm.html.min from the upstream repository
  2. Regenerate the minified template with the project's official minify/build tooling instead of hand-editing
  3. Run Template::parse on the file in a test to pinpoint the exact syntax error
  4. Audit packaging steps (deb/docker) for anything rewriting or truncating resources/
  5. Verify a complete source checkout; include_str! requires the file at compile time

Example fix

// before (hand-edited min template with broken placeholder)
{{ alarm.start|bad_filter }}
// after (restore upstream placeholder syntax)
{{alarm.start}} {{alarm.end}} {{alarm.summary}}
Defensive patterns

Strategy: validation

Validate before calling

// compile-time / CI check that the embedded template parses
#[test]
fn calendar_alarm_template_parses() {
    Template::parse(include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/../../resources/html-templates/calendar-alarm.html.min"
    ))).expect("calendar-alarm template must parse");
}

Try / catch

// Not catchable at runtime: it panics via .expect() during config load.
// Guard at process startup:
let config = match Config::build(...) {
    Ok(c) => c,
    Err(e) | Err(_) if e.to_string().contains("Failed to parse calendar template") => {
        eprintln!("template resource corrupted; reinstall package");
        std::process::exit(1);
    }
};

Prevention

When it happens

Trigger: Constructing GroupwareConfig (groupware settings enabled) where Template::parse on calendar-alarm.html.min returns Err — typically after hand-editing the minified template, running a broken minification, or a parser upgrade that rejects legacy template syntax.

Common situations: Developers editing the .min template directly and breaking placeholder syntax; build/packaging pipelines truncating files under resources/; distribution patches conflicting with a stricter template parser in a newer version; incomplete source checkouts.

Understand the failure class

Related errors


AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06). Data as JSON: /api/errors/2ae749395849aae8. Report an issue: GitHub.