BoundaryML/baml · error · minijinja::Error

UnknownMethod

UnknownMethod

Error message

BamlImage has no callable attribute '{args:#?}'

What it means

BAML exposes BamlImage (media) objects to minijinja templates as MinijinjaBamlMedia, whose Object::call implementation is intentionally a stub that always fails with UnknownMethod. BamlImage instances are not callable, so any attempt to call them like a function or method in a Jinja expression raises "BamlImage has no callable attribute '{args:#?}'".

Source

Thrown at engine/baml-lib/jinja-runtime/src/baml_value_to_jinja_value.rs:133

        )
    }
}

// Necessary for nested instances of MinijinjaBamlImage to get rendered correctly in prompts
// See https://github.com/BoundaryML/baml/pull/855 for explanation
impl std::fmt::Debug for MinijinjaBamlMedia {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        std::fmt::Display::fmt(self, f)
    }
}

impl minijinja::value::Object for MinijinjaBamlMedia {
    fn call(
        self: &Arc<Self>,
        _state: &minijinja::State<'_, '_>,
        args: &[minijinja::value::Value],
    ) -> Result<minijinja::value::Value, minijinja::Error> {
        Err(minijinja::Error::new(
            minijinja::ErrorKind::UnknownMethod,
            format!("BamlImage has no callable attribute '{args:#?}'"),
        ))
    }

    fn is_true(self: &Arc<Self>) -> bool {
        true
    }

    fn render(self: &Arc<Self>, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Display::fmt(self, f)
    }
}

#[derive(Debug)]
pub struct MinijinjaBamlEnumType {
    pub enum_name: String,
    pub enum_values: IndexMap<String, MinijinjaBamlEnumValue>,

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Do not call the image; access its attributes directly (e.g. image.base64, image.media_type) or pass the BamlImage into the LLM media field.
  2. If you need transformation, do it in host code before injecting the image into the template.
  3. Use a registered minijinja filter/function instead of calling the image object itself.
  4. Check template syntax: parentheses after an image variable trigger this; remove them.
  5. Inspect the '{args:#?}' in the message — it shows exactly what call was attempted.

Example fix

// before (template)
{{ image.resize(1024) }}
// after
{{ image.base64 }}  {# attribute access only; resize in host code or via a registered filter #}
Defensive patterns

Strategy: validation

Validate before calling

// In templates, never invoke image objects; attribute access only.
// Host-side guard before rendering:
if template_src.contains(&format!("{{{{ {}(", image_var)) {
    bail!("{image_var} is a BamlImage and is not callable; use attribute access");
}

Type guard

// Attribute-only pattern: {{ image.base64 }} / {{ image.media_type }} — no parentheses after the image variable

Try / catch

match tpl.render(ctx) {
    Ok(out) => out,
    Err(e) if e.kind() == minijinja::ErrorKind::UnknownMethod =>
        bail!("template called a non-callable BamlImage: {e}"),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Writing a template expression that invokes a BamlImage value as if it were a function or method, e.g. {{ image(...) }} or {{ image.attr(...) }}, instead of attribute-only access (image.url, image.base64, image.media_type).

Common situations: Prompt templates that try to post-process images (resize/convert) inside the template, or copying call syntax meant for a registered filter when the correct usage is plain attribute access.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/2673f6c3ba2ee342. Report an issue: GitHub.