Skip to content

Python: [Bug]: Injected Redis context indexes cannot encode optional null message fields #9067

Closed

Description

@ktz03

Description

RedisContextProvider.after_run() cannot write an ordinary message through an injected AsyncSearchIndex with RedisVL's default validate_on_load=False. The provider prepares optional fields such as message_id, author_name, and unset scope IDs as None; Redis HASH command encoding rejects these values before the message can be written.

The provider-created index enables validation and RedisVL already removes null fields on that path. The injected-index path should omit the same null fields, while preserving configured scopes, caller-supplied IDs, and non-null values.

I am taking on a small fix that omits null values from the prepared copies immediately before load(), after embedding generation, with SDK-chain regressions.

Code Sample

The following illustrates the public hook with an injected index; running it against a service requires Redis with Search support and a new index name.

import asyncio
from uuid import uuid4
from unittest.mock import MagicMock

import redis.asyncio as redis
from agent_framework import AgentSession, Message, SessionContext
from agent_framework_redis import RedisContextProvider
from redisvl.index import AsyncSearchIndex

async def main():
    name = f"context-null-repro-{uuid4().hex}"
    client = redis.Redis.from_url("redis://localhost:6379", decode_responses=False)
    template = RedisContextProvider(user_id="user-1", index_name=name, prefix=name)
    index = AsyncSearchIndex.from_dict(template.schema_dict, redis_client=client)
    provider = RedisContextProvider(
        redis_index=index, user_id="user-1", index_name=name, prefix=name
    )
    session = AgentSession(session_id="session-1")
    context = SessionContext(
        session_id=session.session_id,
        input_messages=[Message(role="user", contents=["Remember tea"])],
    )
    try:
        await provider.after_run(
            agent=MagicMock(), session=session, context=context, state={}
        )
    finally:
        await client.aclose()

asyncio.run(main())

Error Messages / Stack Traces

RedisVLError: Failed to load data: Invalid input of type: 'NoneType'.
Convert to a bytes, string, int or float first.

Package Versions

Official main 2df61296bb563a95552b18491ad29b1e1a509f81: agent-framework-core 1.20.0 and agent-framework-redis 1.0.0b261002 source; RedisVL 0.15.0 and redis-py 7.1.1.

Python Version

Python 3.14.3 on Windows.

Additional Context

The failure was verified offline through the actual RedisVL load() / HashStorage / redis-py pipeline and Encoder chain, with index existence/creation and network transport stubbed. No live Redis server, authentication, or model service was tested. The public hook also fails with all application/agent/user scopes configured, because a normal message can still have no message ID or author. Fully populated non-null records are successful controls.

This is separate from #9062/#9063: the reproduction uses a new index and never enters existing-index schema validation. The generic RedisCollection HASH null-rejection contract is also unaffected.

Activity

  1. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 5, 2026
  2. added
    reproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow
    on Oct 5, 2026
  3. github-actions commented on Oct 5, 2026

    @github-actions
    Contributor

    🤖 Automated triage reproduction notes (agent-authored — trust but verify)

    Agent analysis

    Repro: python/packages/redis/agent_framework_redis/_context_provider.py::RedisContextProvider._add at line 352 forwards prepared dictionaries containing None to an injected AsyncSearchIndex whose default validate_on_load=False. The trigger is after_run() with an ordinary message lacking message_id or author_name; unset scope IDs can add more nulls. Minimal repro: inject an AsyncSearchIndex.from_dict(...) and call after_run() with Message(role="user", contents=["Remember tea"]); RedisVL raises RedisVLError wrapping redis-py’s DataError.

    • Failing test: python/packages/redis/tests/test_context_provider_null_fields.py
    • Files examined: python/packages/redis/agent_framework_redis/_context_provider.py, python/packages/redis/tests/test_context_provider_edges.py, python/packages/redis/tests/test_providers.py, python/packages/redis/pyproject.toml, python/packages/redis/tests/test_context_provider_null_fields.py
    • Tests run: test_context_provider_edges.py, owned-index control test, injected-index reproduction test
    • Reported version: agent-framework-redis 1.0.0b261002
    • Current version: agent-framework-redis 1.0.0b261002
  4. added
    memoryUsage: [Issues, PRs], Target: memory related features
    and removed
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

memoryUsage: [Issues, PRs], Target: memory related featurespythonUsage: [Issues, PRs], Target: PythonreproducedUsage: [Issues], Target: all issues that can be reproduced by the triage workflow

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions