HKUDS/Vibe-Trading · error · ValueError

the originating session is not an IM conversation

Error message

the originating session is not an IM conversation

What it means

For origin delivery, the originating session's config must contain a string 'channel' and 'channel_chat_id'. The session exists but is not bound to an IM conversation (or the config keys are missing/wrong types), so there is nowhere to deliver results.

Source

Thrown at agent/src/scheduled_research/service.py:109

        raise ValueError("end_at must include an explicit timezone offset")
    return int(parsed.timestamp() * 1000)


def _origin_target(session_id: str | None) -> tuple[str, str, str | None, str]:
    if not session_id:
        raise ValueError("origin delivery requires the originating session")
    host = sys.modules.get("api_server") or sys.modules.get("agent.api_server")
    service = (
        host._get_session_service()
        if host and hasattr(host, "_get_session_service")
        else None
    )
    session = service.get_session(session_id) if service else None
    config = getattr(session, "config", None) or {}
    channel = config.get("channel")
    target = config.get("channel_chat_id")
    if not isinstance(channel, str) or not isinstance(target, str):
        raise ValueError("the originating session is not an IM conversation")
    return channel, target, None, "当前会话"


def build_job_from_draft(
    draft: Mapping[str, Any],
    *,
    session_id: str | None = None,
    now_ms: int | None = None,
) -> ScheduledResearchJob:
    """Validate the public draft and build a persisted-model job."""
    now = int(time.time() * 1000) if now_ms is None else now_ms
    title = str(draft.get("title") or "").strip()
    if not title:
        raise ValueError("title is required")
    source = draft.get("source")
    schedule_spec = draft.get("schedule")
    delivery_spec = draft.get("delivery") or {"mode": "in_app"}
    if not isinstance(source, Mapping) or not isinstance(schedule_spec, Mapping):

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Create the job from within the IM conversation so the session has channel + channel_chat_id
  2. Verify session.config contains both keys as strings (str() the chat id if numeric)
  3. Use 'configured' delivery with an explicit target_ref if the session can't be IM-bound

Example fix

# before
session.config = {"channel": "telegram"}  # no chat id
# after
session.config = {"channel": "telegram", "channel_chat_id": "12345"}
Defensive patterns

Strategy: type-guard

Validate before calling

cfg = session.config or {}
assert isinstance(cfg.get("channel"), str) and isinstance(cfg.get("channel_chat_id"), str), "session not IM-bound"

Type guard

def session_is_im_conversation(session) -> bool:
    cfg = getattr(session, "config", None) or {}
    return isinstance(cfg.get("channel"), str) and isinstance(cfg.get("channel_chat_id"), str)

Try / catch

try:
    build_job_from_draft(draft, session_id=sid)
except ValueError as e:
    if "not an IM conversation" in str(e):
        suggest_configured_delivery()

Prevention

When it happens

Trigger: Session created via web UI or API without channel binding; config['channel'] set but channel_chat_id missing or numeric; test stub sessions lacking channel fields.

Common situations: Users trying origin delivery from the web app instead of the IM bot; partial session migrations that dropped channel metadata; channels that don't persist chat ids.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/86094dd6316781e0. Report an issue: GitHub.