HKUDS/Vibe-Trading · error · ValueError
end_at must be a valid RFC3339 timestamp
Error message
end_at must be a valid RFC3339 timestamp
What it means
The end_at string could not be parsed by datetime.fromisoformat (after replacing a trailing 'Z' with '+00:00'). The value must be a valid RFC3339/ISO-8601 timestamp.
Source
Thrown at agent/src/scheduled_research/service.py:89
executor = None
if executor is not None:
running = bool(executor.is_running)
return {"enabled": enabled, "running": running, "executable": enabled and running}
def _parse_end_at(value: Any) -> int | None:
if value in (None, ""):
return None
if isinstance(value, bool):
raise ValueError("end_at must be RFC3339 text or epoch milliseconds")
if isinstance(value, int):
return value
if not isinstance(value, str):
raise ValueError("end_at must be RFC3339 text or epoch milliseconds")
try:
parsed = datetime.fromisoformat(value.strip().replace("Z", "+00:00"))
except ValueError as exc:
raise ValueError("end_at must be a valid RFC3339 timestamp") from exc
if parsed.tzinfo is None:
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")View on GitHub (pinned to 80ffdda44c)
Solutions
- Use strict RFC3339 with offset: '2026-12-31T00:00:00+00:00' or 'Z' suffix
- Pre-validate/normalize user input (dateutil, date-fns) before submitting the draft
- Send epoch milliseconds instead if string formatting is fragile in your stack
Example fix
// before
{"end_at": "31/12/2026"}
// after
{"end_at": "2026-12-31T00:00:00Z"} Defensive patterns
Strategy: validation
Validate before calling
from datetime import datetime
def ok(ts: str) -> bool:
try:
datetime.fromisoformat(ts.strip().replace("Z", "+00:00"))
return True
except ValueError:
return False
assert ok(draft["end_at"]) Type guard
def is_rfc3339(s: str) -> bool:
try:
datetime.fromisoformat(s.strip().replace("Z", "+00:00"))
return True
except ValueError:
return False Try / catch
try:
build_job_from_draft(draft)
except ValueError as e:
if "valid RFC3339" in str(e):
prompt_user_for_date() Prevention
- Use standard libraries (date-fns, dateutil) to format RFC3339
- Prefer epoch ms when the client's date formatting is unreliable
When it happens
Trigger: Passing strings like '2026-13-01', 'tomorrow', '12/31/2026', or a malformed ISO string; locale-formatted dates; Python <3.11 rejecting some ISO variants that fromisoformat doesn't support.
Common situations: Human-entered dates from chat/UI not normalized; Python versions prior to 3.11 where fromisoformat is strict about formats; copying dates with unusual separators.
Related errors
- end_at must include an explicit timezone offset
- timezone {tz!r} is not a recognized IANA timezone key
- unknown delivery status {raw_status!r}
- 'failure_kind' must be 'dispatch', 'schedule', or null
- 'source_type' must be 'prompt' or 'playbook'
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/08a320cdd82d23d7.
Report an issue: GitHub.