NousResearch/hermes-agent · error

Timed out connecting to Hermes backend after ${timeoutMs}ms

Error message

Timed out connecting to Hermes backend after ${timeoutMs}ms

What it means

ValueError from create_job (cron/jobs.py:1732): a one-shot ('once') schedule resolved, but compute_next_run() returned None — the requested run_at is more than ONESHOT_GRACE_SECONDS (120s) in the past, so the job would never fire and is rejected at creation instead of sitting dead in the store. A warning is logged alongside.

Source

Thrown at apps/desktop/electron/dashboard-token.ts:23

 * spawns the local dashboard, but the dashboard is the source of truth for the
 * token it actually serves to the renderer. If those drift, HTTP readiness
 * probes still pass while /api/ws rejects the renderer's token.
 */

const DEFAULT_TOKEN_FETCH_TIMEOUT_MS = 3_000

async function fetchPublicText(url, options: any = {}) {
  const { protocol } = new URL(url)

  if (protocol !== 'http:' && protocol !== 'https:') {
    throw new Error(`Unsupported Hermes backend URL protocol: ${protocol}`)
  }

  const timeoutMs = options.timeoutMs ?? DEFAULT_TOKEN_FETCH_TIMEOUT_MS

  const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) }).catch(error => {
    if (error.name === 'TimeoutError') {
      throw new Error(`Timed out connecting to Hermes backend after ${timeoutMs}ms`)
    }

    throw error
  })

  const text = await res.text()

  if (!res.ok) {
    throw new Error(`${res.status}: ${text || res.statusText}`)
  }

  return text
}

function extractInjectedDashboardToken(html) {
  const match = /window\.__HERMES_SESSION_TOKEN__\s*=\s*("(?:\\.|[^"\\])*")/.exec(String(html || ''))

  if (!match) {

View on GitHub (pinned to c896c09c42)

Solutions

  1. Pick a future timestamp, or use a relative duration ('30m', '2h') which is computed from now.
  2. Check the clock and timezone on the host running the cron scheduler — the grace window is only 120s.
  3. For recurring work, use cron/interval schedules instead of one-shot timestamps.

Example fix

# before (at 15:00)
create_job(prompt="report", schedule="2026-08-14T09:00")

# after
create_job(prompt="report", schedule="2026-08-14T16:00")  # or "2h"
Defensive patterns

Strategy: validation

Validate before calling

from datetime import datetime, timedelta
from cron.jobs import ONESHOT_GRACE_SECONDS

def schedulable_one_shot(when: datetime) -> bool:
    return when > datetime.now(when.tzinfo) + timedelta(seconds=ONESHOT_GRACE_SECONDS - 10)

# or skip absolute times entirely and use a duration string: "45m"

Try / catch

try:
    job = create_job(prompt=p, schedule="2026-08-14T09:00")
except ValueError as e:
    if "in the past" in str(e):
        job = create_job(prompt=p, schedule="1h")  # retry relative to now
        raise

Prevention

When it happens

Trigger: create_job with an ISO timestamp like '2025-01-01T09:00' (already past), or a duration so small the time elapsed between parse and validation; also clock skew where the scheduler host's clock is ahead of the client's.

Common situations: User schedules 'today at 9am' after 9am; timestamps built from a stale clock; jobs created on a machine whose timezone/clock differs from the gateway host; DST confusion making a 'future' local time actually past.

Understand the failure class

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/374f6153031aaf09. Report an issue: GitHub.