Summary
The Run markdown documentation tests step (make test-docs-examples, post-merge job) has been failing on every push to main since the 2026-06-26 release push — main is currently red. Five doc code fences fail at decoration time with the same ConfigurationError:
cachekit.config.validation.ConfigurationError: Encryption requires a
cross-SDK-compatible serializer for cross-language interop, got serializer='auto'.
Allowed under encryption: default, std, standard, orjson, arrow.
Failing run: https://github.com/cachekit-io/cachekit-py/actions/runs/28317426425/job/83893200204 (5 failed, 121 passed)
Failing fences (all same root cause)
| # |
File |
Fence |
Serializer |
| 1 |
docs/api-reference.md |
CodeFence#7 (line 471) |
serializer="auto" |
| 2 |
docs/comparison.md |
CodeFence#1 (line 50) |
serializer='auto' |
| 3 |
docs/getting-started.md |
CodeFence#4 (line 117) |
serializer="auto" |
| 4 |
docs/serializers/custom.md |
CodeFence#3 (line 81) |
custom PydanticSerializer (no cross_sdk_compatible=True) |
| 5 |
docs/serializers/pydantic.md |
CodeFence#2 (line 106) |
custom PydanticSerializer (no cross_sdk_compatible=True) |
Root cause
docs/conftest.py:97 sets the master key process-wide for the whole docs session, so @cache.secure examples validate:
# docs/conftest.py:96-97
secret_key = "a" * 64 # 32 bytes in hex
os.environ["CACHEKIT_MASTER_KEY"] = secret_key
Since #127 (auto-detect: encryption turns on globally whenever a master key is present) and #200 (re-read settings when CACHEKIT_MASTER_KEY appears), that ambient key silently flips every plain @cache example into encrypted mode. The v0.6.0 cross-SDK rule then rejects any non-cross-SDK serializer at decoration time — which is exactly what the 5 fences above use (serializer="auto" and custom serializers that don't declare cross_sdk_compatible=True).
This is the same bug tests/conftest.py already hit and fixed (see tests/conftest.py:450-464):
Previously also set CACHEKIT_MASTER_KEY for every test. That broke after the PR #127 auto-detect: any cached settings singleton that captured the env-set master key turned encryption on globally, which the v0.6.0 cross-SDK rule then rejected for non-default serializers. Tests that need encryption now set CACHEKIT_MASTER_KEY locally via monkeypatch.setenv.
docs/conftest.py never got the same treatment — it still sets the key globally.
Reproduction
import os
from cachekit import cache
os.environ["CACHEKIT_MASTER_KEY"] = "a" * 64 # what docs/conftest.py does
@cache(ttl=1800, serializer="auto") # any of the 5 fences
def f():
import numpy as np
return np.array([1, 2, 3])
# -> ConfigurationError at decoration time
Remove the os.environ line and it applies cleanly. Confirmed locally: green without the ambient key, red with it. Only post-merge is affected because the Tests jobs load tests/conftest.py (which neutralizes the key); the docs run does not.
Why this is more than a red build
The examples themselves are correct documentation of a legitimate non-encrypted mode (serializer="auto" for Python-only NumPy/UUID/set data). The harness silently encrypting them means the docs are being tested in a mode they don't claim to demonstrate.
Fix options (maintainer's call)
- A — recommended, mirrors the
tests/conftest.py fix: stop setting CACHEKIT_MASTER_KEY globally in docs/conftest.py. Inject it only into the specific @cache.secure fences that need it, and bracket with reset_settings() so the singleton doesn't leak the key across fences.
- B — docs change: if the intent is that all fences must pass under encryption, rewrite the 5 fences to encryption-compatible serializers (
default/std/orjson/arrow) or set cross_sdk_compatible=True on the custom serializer. This changes what the examples teach, so A is preferable.
Related design discussion: #185 (auto forbidden under encryption regardless of backend).
Summary
The Run markdown documentation tests step (
make test-docs-examples,post-mergejob) has been failing on every push tomainsince the 2026-06-26 release push — main is currently red. Five doc code fences fail at decoration time with the sameConfigurationError:Failing run: https://github.com/cachekit-io/cachekit-py/actions/runs/28317426425/job/83893200204 (
5 failed, 121 passed)Failing fences (all same root cause)
docs/api-reference.mdserializer="auto"docs/comparison.mdserializer='auto'docs/getting-started.mdserializer="auto"docs/serializers/custom.mdPydanticSerializer(nocross_sdk_compatible=True)docs/serializers/pydantic.mdPydanticSerializer(nocross_sdk_compatible=True)Root cause
docs/conftest.py:97sets the master key process-wide for the whole docs session, so@cache.secureexamples validate:Since #127 (auto-detect: encryption turns on globally whenever a master key is present) and #200 (re-read settings when
CACHEKIT_MASTER_KEYappears), that ambient key silently flips every plain@cacheexample into encrypted mode. The v0.6.0 cross-SDK rule then rejects any non-cross-SDK serializer at decoration time — which is exactly what the 5 fences above use (serializer="auto"and custom serializers that don't declarecross_sdk_compatible=True).This is the same bug
tests/conftest.pyalready hit and fixed (seetests/conftest.py:450-464):docs/conftest.pynever got the same treatment — it still sets the key globally.Reproduction
Remove the
os.environline and it applies cleanly. Confirmed locally: green without the ambient key, red with it. Onlypost-mergeis affected because theTestsjobs loadtests/conftest.py(which neutralizes the key); the docs run does not.Why this is more than a red build
The examples themselves are correct documentation of a legitimate non-encrypted mode (
serializer="auto"for Python-only NumPy/UUID/set data). The harness silently encrypting them means the docs are being tested in a mode they don't claim to demonstrate.Fix options (maintainer's call)
tests/conftest.pyfix: stop settingCACHEKIT_MASTER_KEYglobally indocs/conftest.py. Inject it only into the specific@cache.securefences that need it, and bracket withreset_settings()so the singleton doesn't leak the key across fences.default/std/orjson/arrow) or setcross_sdk_compatible=Trueon the custom serializer. This changes what the examples teach, so A is preferable.Related design discussion: #185 (auto forbidden under encryption regardless of backend).