** Please make sure you read the contribution guide and file the issues in the right place. **
Describe the bug
The v0→v1 session migration tool's restricted unpickler (added in 9db48ce9, "fix(migration): restrict unpickling of v0 actions blobs") blocks builtins.getattr, and on Python 3.11 — specifically an environment with the full test extras installed, where crewai[tools] applies per the pyproject marker python_version>='3.11' and python_version<'3.12' — the pickled EventActions graph contains a getattr global. The unpickler rejects it, _safe_unpickle_actions logs a WARNING and falls back to empty actions, and migrated events silently lose requested_auth_configs and compaction.
Observable today as a deterministic unit-test failure on the py311 tox environment:
FAILED tests/unittests/sessions/migration/test_migration.py::test_migrate_from_sqlalchemy_pickle_preserves_nested_safe_actions_pickle
AssertionError: assert 'fc-auth' in {}
with this in the captured log:
WARNING ... Failed to unpickle actions for event event1: Blocked global during migration unpickle: builtins.getattr
To Reproduce
Steps to reproduce (repo at current main):
uv venv --python "python3.11" .venv && source .venv/bin/activate && uv sync --all-extras
pytest "tests/unittests/sessions/migration/test_migration.py::test_migrate_from_sqlalchemy_pickle_preserves_nested_safe_actions_pickle"
- Test fails as above. The same test passes on py310, py312, py313, and py314 tox environments (
tox run: py310 OK, py311 FAIL, py312 OK, py313 OK, py314 OK).
Ruling out version skew: pydantic (2.12.5), fastapi (0.141.1), and google-genai (2.17.0) are identical across the py310/py311/py312 environments — the only material difference in the failing environment is the presence of crewai and its transitive dependencies, which only install on 3.11. A plausible mechanism is a pydantic plugin registered via entry points by one of those transitive dependencies altering how pydantic model instances pickle (introducing a getattr reduction), but I have not bisected the exact package.
Expected behavior
Either the migration unpickler accepts the pickle streams that pydantic models actually produce in every supported environment (so nested EventActions content survives migration), or — if builtins.getattr must stay blocked for hardening reasons — the migration should not silently degrade to {} for blobs a supported environment wrote. Silent data loss during migration is the worst outcome of the current behavior; the test correctly catches it.
Desktop:
- OS: macOS (Darwin 24.6.0)
- Python version: 3.11 (failing); 3.10/3.12/3.13/3.14 (passing)
- ADK version: current
main (c5672030)
Additional context
🤖 Generated with Claude Code
** Please make sure you read the contribution guide and file the issues in the right place. **
Describe the bug
The v0→v1 session migration tool's restricted unpickler (added in
9db48ce9, "fix(migration): restrict unpickling of v0 actions blobs") blocksbuiltins.getattr, and on Python 3.11 — specifically an environment with the fulltestextras installed, wherecrewai[tools]applies per the pyproject markerpython_version>='3.11' and python_version<'3.12'— the pickledEventActionsgraph contains agetattrglobal. The unpickler rejects it,_safe_unpickle_actionslogs a WARNING and falls back to empty actions, and migrated events silently loserequested_auth_configsandcompaction.Observable today as a deterministic unit-test failure on the py311 tox environment:
with this in the captured log:
To Reproduce
Steps to reproduce (repo at current
main):uv venv --python "python3.11" .venv && source .venv/bin/activate && uv sync --all-extraspytest "tests/unittests/sessions/migration/test_migration.py::test_migrate_from_sqlalchemy_pickle_preserves_nested_safe_actions_pickle"toxrun:py310 OK, py311 FAIL, py312 OK, py313 OK, py314 OK).Ruling out version skew: pydantic (2.12.5), fastapi (0.141.1), and google-genai (2.17.0) are identical across the py310/py311/py312 environments — the only material difference in the failing environment is the presence of
crewaiand its transitive dependencies, which only install on 3.11. A plausible mechanism is a pydantic plugin registered via entry points by one of those transitive dependencies altering how pydantic model instances pickle (introducing agetattrreduction), but I have not bisected the exact package.Expected behavior
Either the migration unpickler accepts the pickle streams that pydantic models actually produce in every supported environment (so nested
EventActionscontent survives migration), or — ifbuiltins.getattrmust stay blocked for hardening reasons — the migration should not silently degrade to{}for blobs a supported environment wrote. Silent data loss during migration is the worst outcome of the current behavior; the test correctly catches it.Desktop:
main(c5672030)Additional context
toxmatrix to prepare PR fix: report root_agent type mismatch instead of 'No root_agent found' #6635 (fix for AgentLoader discards its own diagnosis: type mismatch onroot_agentis logged at WARNING, then reported as "No root_agent found" #6606); that diff touches onlycli/utils/agent_loader.py, and this failure reproduces identically on unmodifiedmain.pickle.loads()in v0 schema paths)._ALLOWED_PICKLE_GLOBALSand the blocked-global raise insrc/google/adk/sessions/migration/migrate_from_sqlalchemy_pickle.py(allowlist at line ~41, rejection at line ~113-116).🤖 Generated with Claude Code