# What changed in minijinja

> 69 changes in minijinja 2 to 3 from its official release notes, upgrade guides and advisories: 41 breaking, 20 new APIs and options. Each one cited. Sources checked 2026-10-18. HTML: https://unstale.sh/pypi/minijinja/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## minijinja 3

### Breaking changes

- In Go, the filter now rejects undefined values with strict undefined behavior like in Rust. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- In Go, the filter now rejects undefined values with strict undefined behavior like in Rust. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- The filter compares strings case-insensitively by default and accepts the case_sensitive and attribute arguments for Jinja2 compatibility in Rust and Go. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- The filter compares strings case-insensitively by default and accepts the case_sensitive and attribute arguments for Jinja2 compatibility in Rust and Go. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- In Go, whitespace control, lstrip_blocks and end of line statements now handle all Unicode whitespace rather than only ASCII whitespace. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- AutoEscape::Custom now holds Cow<'static, str>, allowing custom auto escape formats to be determined at runtime; AutoEscape is no longer Copy. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Automatic reloading of individual templates is built in and enabled by default; loaders can return TemplateSource with an up-to-date check. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The custom_syntax feature was removed; custom delimiters, line statements and line comments are now always available. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The dist/bundler package path is gone. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The dist/node package path is gone. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The dist/web package path is gone. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Division by zero now produces an error. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The loader is now generic over its returned source, which may be a String or TemplateSource; some closures need an explicit return type. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The CLI no longer supports Fig completions. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Floor division now follows Jinja2 semantics. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The format filter moved to the formatting module and was renamed from format_filter. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Rendering APIs, context! and args! now consume values and convert exclusively through Into<Value>. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The json feature no longer depends on serde or serde_json; JSON output uses a built-in serializer and invalid values now fail serialization. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Building the Python bindings now requires maturin 1.9.4 or later. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- 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. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The modulo operator now follows Jinja2 semantics. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The Python bindings now require Python 3.10 or later. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- 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. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Typed render-local extensions can persist through includes, blocks and macros. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The round filter now uses round-half-even semantics and fixes decimal rounding edge cases. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The sequence test now classifies undefined values as sequences. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Serde is now optional and disabled by default; enable the feature to use Serde conversion, which is requested explicitly with value::Serde. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Mutable State is now the canonical path for callbacks and nested macro calls; state mutation and dynamic calls require &mut State. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- This method was removed in favor of typed render-local extensions. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Custom date/time formats now use strftime-style syntax instead of time format descriptions. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- trim_blocks, lstrip_blocks and keep_trailing_newline settings moved from Environment into SyntaxConfig. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- This deprecated Rust API was removed in MiniJinja 3. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- This deprecated Rust API was removed in MiniJinja 3. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- This deprecated Rust API was removed in MiniJinja 3. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- JavaScript errors are now raised as TemplateError with kind, detail, templateName, line, range and templateSource properties. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The title filter now starts words after whitespace or selected punctuation, matching Jinja2; for example, don't renders as Don't. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Construct a Value from pairs; collecting pairs directly into Value now creates a sequence of tuples rather than a map. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- This API was removed; use the new explicit Serde conversion mechanism when Serde support is enabled. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Wrap values with value::Serde to request Serde conversion; it also replaces ViaDeserialize for deserializing function arguments. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Variadic functions that intentionally capture keyword arguments can use ValueOrKwargs; Value function arguments no longer accept implicit keyword-argument values. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)

### New APIs and options

- 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. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- 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. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- The JavaScript bindings add addFunction and other APIs for functions, filters, tests, auto escaping, finalization and template introspection. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Use this method to disable built-in automatic template reloading. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Set a seed source for random functions on platforms without a source of randomness. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- An optional JavaScript date/time module provides datetimeformat, dateformat, timeformat and now() using native runtime time zone support. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- This entry point allows initializing the JavaScript module manually. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The JavaScript bindings add the pycompat property. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The JavaScript bindings enable the rand contrib feature, providing random, randrange and lipsum seeded from Math.random. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The JavaScript bindings add removeFilter to remove a filter. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The JavaScript bindings add removeTest to remove a test. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The context argument is now optional for renderStr, renderTemplate, renderNamedStr and evalExpr. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- SafeString marks strings that should not be auto escaped; callbacks can receive and return them to bypass auto escaping. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- JavaScript callbacks wrapped with passState receive a State object to look up variables, inspect template and auto escape state, and apply filters and tests. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- The JavaScript bindings add a syntax property for custom delimiters and line statements. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Use to_builder to modify an existing SyntaxConfig. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Tuple literals and public tuple value types are supported; tuples preserve their type through serialization and sequence operations and render like Python tuples. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- In debug mode, undefined values remember where they were created, and related errors report the expression that produced them and its origin when elsewhere. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Use ValueIter::checked to report errors when iterators yield invalid values, matching the new consistent iteration behavior. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)

### Behavior and default changes

- Templates reload through a shared reference, so the environment no longer needs to be recreated or guarded by a lock. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)

### Fixes and other changes

- The Go filter now uses keyword arguments, passed as a trailing mapping, to fill %(name)s specs like in Rust. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- The Python package is now published as Pyodide wheels for Pyodide 0.29 and 314, so it can be installed with micropip. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- Syntax errors about unexpected characters now show the character rather than its first byte. (3.0.1) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.1)
- pass_state now works on methods invoked from templates. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)
- Corrected the spelling of the JavaScript undefined behavior value from semi_strct to semi_strict. (3.0.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/3.0.0)

## minijinja 2

### Breaking changes

- String repetition is limited to 100 MB in Rust and Go to prevent excessive memory allocations. (2.24.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/2.24.0)

### New APIs and options

- The `wordwrap` filter is now available in the Python bindings. (2.24.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/2.24.0)

### Fixes and other changes

- Conditional expressions in keyword argument values now work compatibly with Jinja2 in Rust and Go. (2.24.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/2.24.0)
- Sorting keys in `context!` is fixed when the `preserve_order` feature is enabled. (2.24.0) — [release notes](https://github.com/mitsuhiko/minijinja/releases/tag/2.24.0)
