NousResearch/hermes-agent · error
Unsupported Hermes backend URL protocol: ${protocol}
Error message
Unsupported Hermes backend URL protocol: ${protocol} What it means
ValueError from _validate_execution_mode (cron/jobs.py:1563): no_agent=True was set but no script was supplied. A no_agent job's entire body is the script — with neither an agent turn nor a script there is literally nothing to execute. Shared by create_job and update_job, so later updates can't create an empty no_agent job either.
Source
Thrown at apps/desktop/electron/dashboard-token.ts:16
/**
* Helpers for local dashboard session-token discovery.
*
* The desktop main process can pass HERMES_DASHBOARD_SESSION_TOKEN when it
* 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}`)
}
View on GitHub (pinned to c896c09c42)
Solutions
- Supply a script when using no_agent: create_job(..., no_agent=True, script='./collect.sh').
- If you want the model to run, just omit no_agent (default False) and keep the prompt.
- When updating, include both {'no_agent': True, 'script': ...} in the same call.
Example fix
# before create_job(prompt="gather data", schedule="1h", no_agent=True) # after create_job(prompt="gather data", schedule="1h", no_agent=True, script="python gather.py > out.json")
Defensive patterns
Strategy: validation
Validate before calling
def valid_no_agent(no_agent: bool, script) -> bool:
return (not no_agent) or bool(script) # no_agent demands a script body Try / catch
try:
create_job(..., no_agent=True)
except ValueError as e:
if "requires a script" in str(e):
create_job(..., no_agent=True, script="./run.sh")
raise Prevention
- Treat no_agent + script as an atomic pair — always set them together.
- Remember the prompt does NOT run in no_agent mode; only the script executes.
When it happens
Trigger: create_job(prompt=..., no_agent=True) with no script=; or update_job(id, {'no_agent': True}) on a job whose script is None/empty.
Common situations: Copy-pasting a job template and deleting the script line; assuming the prompt still runs without an agent (it doesn't); enabling no_agent as a 'cost saving' without providing the replacement workload.
Related errors
- Remote gateway URL must be http:// or https://, got ${parsed
- Preview mode — launching is disabled.
- no install root
- ${isPosix ? 'install.sh --manifest' : 'install.ps1 -Manifest
- Remote connection is not ready yet. Try again in a moment.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/47d6a1e701f9caed.
Report an issue: GitHub.