Skip to content

bug: json.dumps called on Pydantic/external objects without default= handler — latent serialization crashes #473

@axisrow

Description

@axisrow

Problem

json.dumps is called in several places on objects that may contain non-serializable types (datetime, bytes, Pydantic models, Telethon TL objects) without a default= fallback. These are latent crashes that only surface when specific data shapes are encountered at runtime.

Already fixed in #470: Collector._get_service_action_payload crashed with TypeError: datetime is not JSON serializable and then bytes is not JSON serializable on MessageActionChatJoinedByRequest.

Found instances (HIGH risk)

src/database/repositories/collection_tasks.py ~line 93

return json.dumps(payload)

payload is a TaskPayload Pydantic model passed directly — should be .model_dump() first. Pydantic v2 models are not JSON-serializable by default.

src/database/repositories/telegram_commands.py lines 51, 54, 177, 185, 200

json.dumps(command.payload)
json.dumps(command.result_payload)

payload and result_payload originate from Telegram command dispatch — may contain datetime, bytes, or nested TL objects depending on command type.

src/web/routes/pipelines.py lines 577, 584, 588

yield f"data: {json.dumps(data)}\n\n"

data comes from pipeline execution result — may contain Pydantic model instances or other non-serializable types. SSE stream crash here is silent from the client perspective.

Medium risk (needs review)

File Line Note
src/services/agent_provider_service.py ~168 json.dumps(payload) — verify payload is clean dict
src/services/image_provider_service.py ~122 json.dumps(payload) — ImageProviderConfig may have custom types
src/agent/manager.py 271, 290, 301, 742 Multiple json.dumps on agent payloads — verify all values are primitives

Recommended fix pattern

Define a shared utility in src/utils/json.py (or src/database/json_utils.py):

import json
from datetime import datetime, date

def safe_json_dumps(obj, **kwargs) -> str:
    def _default(o):
        if isinstance(o, (datetime, date)):
            return o.isoformat()
        if isinstance(o, bytes):
            return o.hex()
        # Pydantic v2
        if hasattr(o, "model_dump"):
            return o.model_dump()
        return repr(o)
    return json.dumps(obj, default=_default, **kwargs)

Replace all unsafe json.dumps calls on external/untyped data with safe_json_dumps.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions