Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions planning/releases/2.26.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# modern-di 2.26.0 β€” every exception links its troubleshooting page

Back-compatible: no behavior flips, no new warnings, no attribute or
hierarchy changes. The only change is message text β€” every exception now
ends with a stable docs URL, and the docs grew a page for each one.

## Feature

- **Stable per-exception docs URLs (ERR-4).** Every concrete
`ModernDIError` subclass carries a class-level `docs_slug`, and its
message now ends with a uniform final line:
`See: https://modern-di.modern-python.org/troubleshooting/<slug>/`.
The trailer composes with every message shape β€” plain errors,
dependency-path breadcrumbs, and `ValidationFailedError`'s grouped
report alike (path first, trailer always last).
`DuplicateProviderTypeError`'s hand-rolled inline URL is replaced by
the same mechanism (URL unchanged).
- **Complete troubleshooting registry (DOC-6).** 16 new pages under
`/troubleshooting/` β€” one per concrete exception, 21 in total β€” each
with Symptom, Cause, Fix, and escape hatches where real. The
[exception catalog](https://modern-di.modern-python.org/providers/errors-and-exceptions/)
links each entry to its page.
- **Warnings link their exact migration section.** The three transitional
warnings (`UnvalidatedContainerWarning`, `ContainerClosedWarning`,
`ContextValueNoneWarning`) now link the specific
[to-3.x guide](https://modern-di.modern-python.org/migration/to-3.x/)
section anchor for their switch instead of the guide's landing page.

## Why

ERR-4 and DOC-6 from the 2026-07-05 3.0 UX research: a user holding a
production traceback had no stable link to follow β€” of ~20 exception
classes, only one carried a URL. Field precedent: Angular's NGxxxx
registry, Spring's Description/Action reports, wireup's remedy+URL
messages. A census test now walks `modern_di.exceptions` and asserts
every concrete class has a unique slug and an existing page β€” new
exceptions cannot ship without one.

## Downstream

Tests asserting **exact** exception messages will break on the new
trailer line. As with 2.24.0: prefer `pytest.raises(..., match=...)`
with a substring β€” the trailer is a separate final line, so substring
matches survive. No floor bumps required.

## Internals

- 100% line coverage maintained across Python 3.10–3.14; `ruff` and
`ty` clean; docs built under `mkdocs --strict` in CI (which validates
every slug URL has a page).