diff --git a/CHANGELOG.md b/CHANGELOG.md
index dba4b8c..3367ab1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
---
+## v26.06.96 (2026-06-10)
+
+### Fixed
+
+- **`Any` / `Any | None` parameters are no longer autowired.** A constructor or
+ `@bean`-method parameter typed `Any` (e.g. `registry: Any = None`) or `Any | None`
+ (e.g. `metrics: Any | None = None`) was resolved against the container, matching
+ whatever bean was registered under `Any` (such as an `@bean ... -> Any` cache health
+ indicator). That injected the wrong object, e.g. `'CacheHealthIndicator' object has
+ no attribute 'counter'` landing in `RuleEngineService(metrics=...)`. `Any` is now
+ treated like `type` — not injectable — so the parameter falls back to its default.
+ Regression tests in `tests/container/test_any_not_injectable.py`.
+
+---
+
## v26.06.95 (2026-06-10)
### Fixed
diff --git a/README.md b/README.md
index 0c4c9de..ff106c3 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
-
+
diff --git a/pyproject.toml b/pyproject.toml
index 17b6ee5..d949537 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ name = "pyfly"
# CalVer YY.MM.PATCH — package metadata uses PEP 440 normalized form (26.5.4);
# git tag, GitHub release and human-readable display use leading-zero form
# (v26.05.04) to match the Java/.NET/Go siblings.
-version = "26.6.95"
+version = "26.6.96"
description = "The official Python implementation of the Firefly Framework — DI, CQRS, EDA, hexagonal architecture, and more."
readme = "README.md"
license = "Apache-2.0"
diff --git a/src/pyfly/container/container.py b/src/pyfly/container/container.py
index 7b5e566..3b1692c 100644
--- a/src/pyfly/container/container.py
+++ b/src/pyfly/container/container.py
@@ -543,7 +543,12 @@ def _resolve_param(self, param_type: type) -> Any:
# Fast path: a plain class dependency — no typing origin and not a PEP 604 union.
if origin is None and not isinstance(param_type, types.UnionType):
- if param_type is type:
+ # `type` and `Any` are not injectable dependencies — let the caller fall back
+ # to the parameter's default (NoSuchBeanError + has_default => use default).
+ # `Any` must NOT be resolved: it would match whatever bean happens to be
+ # registered under `Any` (e.g. an `@bean ... -> Any`), injecting the wrong
+ # object — e.g. a CacheHealthIndicator landing in `registry: Any = None`.
+ if param_type is type or param_type is Any:
raise NoSuchBeanError(bean_type=None)
return self.resolve(param_type)
@@ -565,6 +570,11 @@ def _resolve_param(self, param_type: type) -> Any:
args = get_args(param_type)
non_none = [a for a in args if a is not type(None)]
if len(non_none) == 1:
+ # Optional[Any] (`Any | None`) is not an injectable dependency — `Any`
+ # would match whatever bean happens to be registered under `Any`,
+ # injecting the wrong object. Leave it unset (None).
+ if non_none[0] is Any:
+ return None
try:
return self.resolve(non_none[0])
except (NoSuchBeanError, NoUniqueBeanError):
diff --git a/tests/container/test_any_not_injectable.py b/tests/container/test_any_not_injectable.py
new file mode 100644
index 0000000..0b87803
--- /dev/null
+++ b/tests/container/test_any_not_injectable.py
@@ -0,0 +1,24 @@
+"""Regression: ``Any`` / ``Any | None`` parameters are NOT injectable.
+
+A parameter typed ``Any`` (or ``Any | None``) must fall back to its default
+instead of resolving to whatever bean happens to be registered under ``Any``
+(e.g. an ``@bean ... -> Any``). Injecting the wrong object caused
+`'CacheHealthIndicator' object has no attribute 'counter'` at startup when such a
+value landed in ``RuleEngineService(metrics: Any | None = None)``.
+"""
+
+from typing import Any
+
+import pytest
+
+from pyfly.container.container import Container
+from pyfly.container.exceptions import NoSuchBeanError
+
+
+def test_plain_any_is_not_injectable() -> None:
+ with pytest.raises(NoSuchBeanError):
+ Container()._resolve_param(Any)
+
+
+def test_optional_any_resolves_to_none() -> None:
+ assert Container()._resolve_param(Any | None) is None
diff --git a/uv.lock b/uv.lock
index 90fbc76..d57ed1b 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2160,7 +2160,7 @@ wheels = [
[[package]]
name = "pyfly"
-version = "26.6.95"
+version = "26.6.96"
source = { editable = "." }
dependencies = [
{ name = "pydantic" },