Found while fixing #222 (PR #224 — its CI run tripped over this).
Repro
With REDIS_URL (or CACHEKIT_REDIS_URL) set in the environment — as it is in CI and most deployments:
>>> import os; os.environ["REDIS_URL"] = "redis://localhost:6379"
>>> from cachekit.backends.redis.config import RedisBackendConfig
>>> RedisBackendConfig(redis_url="redis://cfg-host:7000")
pydantic_core._pydantic_core.ValidationError: 1 validation error for RedisBackendConfig
redis_url
Extra inputs are not permitted [type=extra_forbidden, input_value='redis://cfg-host:7000', input_type=str]
Without the env var set, the same call works.
Why
redis_url has validation_alias=AliasChoices("CACHEKIT_REDIS_URL", "REDIS_URL"). When the env source supplies a value, it enters the merged input keyed by the alias; the field is then populated via the alias, and the redis_url constructor kwarg is left unconsumed — which extra="forbid" rejects. populate_by_name=True only helps when no alias key is present.
Impact
- The documented "Configuration via Python" example (
docs/backends/redis.md) cannot be constructed in any environment that has REDIS_URL set — i.e. exactly the environments where you'd want to override it explicitly.
tests/performance/test_file_backend_perf.py constructs this config inside a try/except and silently skips when it blows up.
- Doctests in
RedisBackendConfig pass only because the doctest environment doesn't set the env vars.
Constraints on a fix
Naively adding "redis_url" to the AliasChoices interacts badly with case_sensitive=False — the field-name alias would match the REDIS_URL env var case-insensitively and could invert the documented CACHEKIT_REDIS_URL > REDIS_URL priority. Likely needs either a mode="before" validator that reconciles the alias/name keys (init value must win — matching #222's "explicit argument wins" principle) or a rethink of how the env aliases are attached. Same pattern applies to any future field given a validation_alias.
Found while fixing #222 (PR #224 — its CI run tripped over this).
Repro
With
REDIS_URL(orCACHEKIT_REDIS_URL) set in the environment — as it is in CI and most deployments:Without the env var set, the same call works.
Why
redis_urlhasvalidation_alias=AliasChoices("CACHEKIT_REDIS_URL", "REDIS_URL"). When the env source supplies a value, it enters the merged input keyed by the alias; the field is then populated via the alias, and theredis_urlconstructor kwarg is left unconsumed — whichextra="forbid"rejects.populate_by_name=Trueonly helps when no alias key is present.Impact
docs/backends/redis.md) cannot be constructed in any environment that hasREDIS_URLset — i.e. exactly the environments where you'd want to override it explicitly.tests/performance/test_file_backend_perf.pyconstructs this config inside a try/except and silently skips when it blows up.RedisBackendConfigpass only because the doctest environment doesn't set the env vars.Constraints on a fix
Naively adding
"redis_url"to the AliasChoices interacts badly withcase_sensitive=False— the field-name alias would match theREDIS_URLenv var case-insensitively and could invert the documentedCACHEKIT_REDIS_URL > REDIS_URLpriority. Likely needs either amode="before"validator that reconciles the alias/name keys (init value must win — matching #222's "explicit argument wins" principle) or a rethink of how the env aliases are attached. Same pattern applies to any future field given avalidation_alias.