pypi / minijinja
minijinja
What changed in minijinja 2 to 3, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-18.
41 breaking20 new APIs and options1 behavior and defaults7 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli initminijinja 365 changes
Breaking changes 40
In Go, the filter now rejects undefined values with strict undefined behavior like in Rust.
In Go, the filter now rejects undefined values with strict undefined behavior like in Rust.
The filter compares strings case-insensitively by default and accepts the case_sensitive and attribute arguments for Jinja2 compatibility in Rust and Go.
The filter compares strings case-insensitively by default and accepts the case_sensitive and attribute arguments for Jinja2 compatibility in Rust and Go.
In Go, whitespace control, lstrip_blocks and end of line statements now handle all Unicode whitespace rather than only ASCII whitespace.
AutoEscape::Custom now holds Cow<'static, str>, allowing custom auto escape formats to be determined at runtime; AutoEscape is no longer Copy.
Automatic reloading of individual templates is built in and enabled by default; loaders can return TemplateSource with an up-to-date check.
The custom_syntax feature was removed; custom delimiters, line statements and line comments are now always available.
The dist/bundler package path is gone.
The dist/node package path is gone.
The dist/web package path is gone.
Division by zero now produces an error.
The loader is now generic over its returned source, which may be a String or TemplateSource; some closures need an explicit return type.
The CLI no longer supports Fig completions.
Floor division now follows Jinja2 semantics.
The format filter moved to the formatting module and was renamed from format_filter.
Rendering APIs, context! and args! now consume values and convert exclusively through Into<Value>.
The json feature no longer depends on serde or serde_json; JSON output uses a built-in serializer and invalid values now fail serialization.
Building the Python bindings now requires maturin 1.9.4 or later.
The npm package is now an ES module with a single wasm build and exports map; Node.js loads wasm synchronously while browsers and other listed runtimes use top-level await.
The modulo operator now follows Jinja2 semantics.
The Python bindings now require Python 3.10 or later.
Templates accessing Python data typically render 3 to 10 times faster; renders no longer release the GIL, and free-threaded Python renders scale with the number of threads.
Typed render-local extensions can persist through includes, blocks and macros.
The round filter now uses round-half-even semantics and fixes decimal rounding edge cases.
The sequence test now classifies undefined values as sequences.
Serde is now optional and disabled by default; enable the feature to use Serde conversion, which is requested explicitly with value::Serde.
Mutable State is now the canonical path for callbacks and nested macro calls; state mutation and dynamic calls require &mut State.
This method was removed in favor of typed render-local extensions.
Custom date/time formats now use strftime-style syntax instead of time format descriptions.
trim_blocks, lstrip_blocks and keep_trailing_newline settings moved from Environment into SyntaxConfig.
This deprecated Rust API was removed in MiniJinja 3.
This deprecated Rust API was removed in MiniJinja 3.
This deprecated Rust API was removed in MiniJinja 3.
JavaScript errors are now raised as TemplateError with kind, detail, templateName, line, range and templateSource properties.
The title filter now starts words after whitespace or selected punctuation, matching Jinja2; for example, don't renders as Don't.
Construct a Value from pairs; collecting pairs directly into Value now creates a sequence of tuples rather than a map.
This API was removed; use the new explicit Serde conversion mechanism when Serde support is enabled.
Wrap values with value::Serde to request Serde conversion; it also replaces ViaDeserialize for deserializing function arguments.
Variadic functions that intentionally capture keyword arguments can use ValueOrKwargs; Value function arguments no longer accept implicit keyword-argument values.
New APIs and options 19
The filter accepts a default argument for Jinja2 compatibility in Rust and Go; a supplied default is returned for values that cannot be converted and for none.
The filter accepts default and base arguments for Jinja2 compatibility in Rust and Go; a supplied default is returned for values that cannot be converted and for none.
The JavaScript bindings add addFunction and other APIs for functions, filters, tests, auto escaping, finalization and template introspection.
Use this method to disable built-in automatic template reloading.
Set a seed source for random functions on platforms without a source of randomness.
An optional JavaScript date/time module provides datetimeformat, dateformat, timeformat and now() using native runtime time zone support.
This entry point allows initializing the JavaScript module manually.
The JavaScript bindings add the pycompat property.
The JavaScript bindings enable the rand contrib feature, providing random, randrange and lipsum seeded from Math.random.
The JavaScript bindings add removeFilter to remove a filter.
The JavaScript bindings add removeTest to remove a test.
The context argument is now optional for renderStr, renderTemplate, renderNamedStr and evalExpr.
SafeString marks strings that should not be auto escaped; callbacks can receive and return them to bypass auto escaping.
JavaScript callbacks wrapped with passState receive a State object to look up variables, inspect template and auto escape state, and apply filters and tests.
The JavaScript bindings add a syntax property for custom delimiters and line statements.
Use to_builder to modify an existing SyntaxConfig.
Tuple literals and public tuple value types are supported; tuples preserve their type through serialization and sequence operations and render like Python tuples.
In debug mode, undefined values remember where they were created, and related errors report the expression that produced them and its origin when elsewhere.
Use ValueIter::checked to report errors when iterators yield invalid values, matching the new consistent iteration behavior.
Behavior and default changes 1
Templates reload through a shared reference, so the environment no longer needs to be recreated or guarded by a lock.
Fixes and other changes 5
The Go filter now uses keyword arguments, passed as a trailing mapping, to fill %(name)s specs like in Rust.
The Python package is now published as Pyodide wheels for Pyodide 0.29 and 314, so it can be installed with micropip.
Syntax errors about unexpected characters now show the character rather than its first byte.
pass_state now works on methods invoked from templates.
Corrected the spelling of the JavaScript undefined behavior value from semi_strct to semi_strict.
minijinja 24 changes
Breaking changes 1
String repetition is limited to 100 MB in Rust and Go to prevent excessive memory allocations.
New APIs and options 1
The
wordwrapfilter is now available in the Python bindings.
Fixes and other changes 2
Conditional expressions in keyword argument values now work compatibly with Jinja2 in Rust and Go.
Sorting keys in
context!is fixed when thepreserve_orderfeature is enabled.