# What changed in multidict

> 39 changes in multidict 6 to 7 from its official release notes, upgrade guides and advisories: 7 breaking, 1 deprecations, 5 security, 4 new APIs and options. Each one cited. Sources checked 2026-10-21. HTML: https://unstale.sh/pypi/multidict/

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

## multidict 7

### Breaking changes

- A str subclass's own lower() is no longer called to compute a key's case-insensitive identity; the identity comes from str.lower(). (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- keys() and iteration yield each distinct key once, spelled as in its first item; items(), values(), and len(d) still include every item. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- The build-time requirement is now setuptools >= 77.0 following the metadata and license metadata changes. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- The C extension now raises TypeError when an argument is passed both positionally and by name, rather than silently misbehaving or ignoring surplus arguments. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- The free-threaded build now requires CPython 3.14 or newer; older free-threaded interpreters fail with a clear compiler error, while GIL builds still support Python 3.10 and newer. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- istr is final and can no longer be subclassed on either backend; code that subclassed it must wrap or convert instead. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)

### Security

- The pair is removed before result construction can run Python code that mutates the multidict, preventing a C-extension use-after-free and a pure-Python length miscount. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- On Python 3.10 and 3.11, mutation during value-list allocation is refused with RuntimeError, avoiding a use-after-free. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)

### Deprecations

- Access emits DeprecationWarning, and the alias is removed from multidict.__all__; it is slated for removal in the next major release. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)

### New APIs and options

- A public C API lets third-party extensions create, read, and mutate multidicts without going through the Python-level API. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- A cimport-able Cython API is available for third-party Cython modules to work with multidicts through the public API. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Provides the include path for the public C API header used by third-party extensions. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- C extensions can register watchers to receive multi-value-aware notifications after a MultiDict or CIMultiDict change operation finishes. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)

### Performance

- Mappings with exact istr keys use a compact table, taking each identity from the key's canonical form and cutting size by about 45%. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- Mappings with exact str keys use a compact table without a separate identity or hash per entry; clear() allows compact storage to start again after another key requires the full layout. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- Constructing a subclass of CIMultiDict got about 1% cheaper. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- The C extension substantially speeds up operations keyed by plain str, including lookups, insertion, construction, extend(), and construction from a dict. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- The C extension’s getall() is a little faster for keys with many values because collected values are no longer copied into a larger buffer as they accumulate. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Argument parsing in the C extension is faster for methods taking key, including their all-positional form and keyword arguments. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Constructing a subclass of MultiDict got about 1% cheaper. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- The C extension improves lookup, insertion, deletion, iteration, and view-set performance; on free-threaded builds, concurrent mutations and lock-free reads are also faster. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Popping every item from a C-extension mapping now takes linear rather than quadratic time. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Key identity conversion and hashing now happen before the lock is taken, narrowing the critical section in free-threaded builds. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)

### Fixes and other changes

- The C extension now takes case-sensitivity mode from the instance, so calling MultiDict.__init__ on a CIMultiDict does not make it case-sensitive, and CIMultiDict.__init__ accepts a MultiDict. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- Fixed version values being truncated on Windows and 32-bit platforms, and a pure-Python race that could give concurrently mutated multidicts the same version. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- Reinitializing a live multidict now installs its new contents and size before releasing old pairs, avoiding lost or leaked finalizer additions and incorrect length. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- Python code that reads or mutates a multidict during initialization, updates, merges, deletion, popall, or related operations no longer causes crashes, lost or duplicated pairs, or backend disagreements. (7.1.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.1.0)
- The C extension now propagates MemoryError and KeyboardInterrupt raised by a positional argument's __len__ while estimating update size, matching the pure-Python backend. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Fixed a spurious RuntimeError when garbage collection mutated the multidict while getall() was building its result. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Fixed a data race on the free-threaded C extension by using relaxed atomic loads and stores for the multidict version counter. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)
- Pure-Python MultiDict and CIMultiDict now convert canonical keys to exact str instances without invoking object.__str__() overrides, matching the C extension. (7.0.0) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v7.0.0)

## multidict 6

### Breaking changes

- Calls that catch a list shrinking while it is being processed now raise RuntimeError, avoiding reads of freed memory on free-threaded builds. (6.9.1) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)

### Security

- Fixed freed-memory reads while iterating keys that are plain str, including when key conversion runs Python code or suspends a free-threaded critical section. (6.9.1) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)
- Fixed a free-threaded use-after-free when lock-free get, item lookup, or membership reads raced with a hash-table resize. (6.9.1) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)
- Multidict: Reference leak in CIMultiDict/MultiDict items-view union and subtraction (6.9.1) — [security advisory](https://github.com/advisories/GHSA-54P9-H82J-F925), [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)

### Fixes and other changes

- Copying or re-initializing from another multidict now assigns a new version in the C extension, matching the pure Python implementation. (6.9.1) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)
- Fixed a free-threaded data race between lock-free reads and freeing a retired hash table. (6.9.1) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)
- Fixed free-threaded concurrent writes that could lose a key, and fixed setdefault inserting a duplicate instead of recognizing an in-flight key. (6.9.1) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)
- Deferred decrefs until mutations finish, fixing a standard C extension segmentation fault when a value finalizer releases the GIL during mutation. (6.9.1) — [release notes](https://github.com/aio-libs/multidict/releases/tag/v6.9.1)
