Skip to content

ParamTypeMismatchForName in 6.3.2 #711

@ehuss

Description

@ehuss

When updating to 6.3.2, we are having an issue with the following error:

RenderError { template_name: Some("an-included-file"), line_no: Some(3), column_no: Some(5), reason: ParamTypeMismatchForName("lower", "s", "str"), unimplemented: false }

The following is a partially minimized example that illustrates this:

# Cargo.toml
[package]
name = "foo"
edition = "2024"

[dependencies]
handlebars = { version = "6.3.1", features = ["dir_source"] }
serde_json = "1.0.140"
// src/main.rs
use handlebars::{
    handlebars_helper, Context, Decorator, DirectorySourceOptions, Handlebars, RenderContext,
    RenderError,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut handlebars = Handlebars::new();
    handlebars.register_decorator("set", Box::new(set_decorator));
    handlebars.register_helper("lower", Box::new(lower));

    let mut options = DirectorySourceOptions::default();
    options.tpl_extension = ".md".to_string();
    let includes = std::env::current_dir().unwrap();
    handlebars.register_templates_directory(includes, options)?;
    let data = serde_json::json!({});
    assert_eq!(
        handlebars
            .render_template(
                r#"
{{~*set somevalue="Example"}}
{{> an-included-file }}
"#,
                &data
            )
            .unwrap(),
        "This file is included.\n\nSee example\n"
    );

    Ok(())
}

handlebars_helper!(lower: |s: str| s.to_lowercase());

/// `{{*set var=value}}` decorator.
///
/// This sets a variable to a value within the template context.
fn set_decorator(
    d: &Decorator<'_>,
    _: &Handlebars<'_>,
    _ctx: &Context,
    rc: &mut RenderContext<'_, '_>,
) -> Result<(), RenderError> {
    let data_to_set = d.hash();
    for (k, v) in data_to_set {
        set_in_context(rc, k, v.value().clone());
    }
    Ok(())
}

/// Sets a variable to a value within the context.
fn set_in_context(rc: &mut RenderContext<'_, '_>, key: &str, value: serde_json::Value) {
    let mut gctx = match rc.context() {
        Some(c) => (*c).clone(),
        None => Context::wraps(serde_json::Value::Object(serde_json::Map::new())).unwrap(),
    };
    if let serde_json::Value::Object(m) = gctx.data_mut() {
        m.insert(key.to_string(), value);
        rc.set_context(gctx);
    } else {
        panic!("expected object in context");
    }
}

And the following file called an-included-file.md:

This file is included.

See {{lower somevalue}}

Running this with 6.3.1 succeeds, but 6.3.2 fails.

A general outline of what this is doing:

  • A set helper used to set variables from within a template.
  • A lower helper which is used to lowercase a value.
  • A directory source to load includes from the current directory.
  • A root template that sets a variable using set, and then an include of a file that is intended to call lower on that value.

I'm not clear what is going on or what the error message means.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions