{"record":{"id":"dc45fac25a7b853a","repo":"NousResearch/hermes-agent","slug":"hermes-backend-did-not-become-ready-detail","errorCode":null,"errorMessage":"Hermes backend did not become ready: ${detail}","messagePattern":"Hermes backend did not become ready: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"apps/desktop/electron/backend-health.ts","lineNumber":168,"sourceCode":"\n      // An explicitly missing route means the backend predates /api/health.\n      // So does a gate-shaped 401 on an ANONYMOUS probe: the dashboard auth\n      // gate runs ahead of the SPA catch-all, so a pre-/api/health backend\n      // rejects the unknown path as unauthenticated instead of 404 and a\n      // credential-free probe can never observe the 404. Timeouts, 5xx, 429,\n      // and non-gate 401s keep polling health.\n      if (!useStatusFallback && (isMissingHealthEndpointError(error) || isGatedMissingHealthError(error))) {\n        useStatusFallback = true\n\n        continue\n      }\n\n      await sleep(pollMs)\n    }\n  }\n\n  const detail = lastError instanceof Error ? lastError.message : 'timeout'\n  throw new Error(`Hermes backend did not become ready: ${detail}`)\n}\n","sourceCodeStart":150,"sourceCodeEnd":170,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/backend-health.ts#L150-L170","documentation":"RuntimeError raised in load_jobs() (cron/jobs.py:1094) when reading ~/.hermes/cron/jobs.json raises an IOError that the auto-repair path could not prevent — e.g. permission denied, disk I/O error, or a read failure on a file that exists. It is distinct from the corruption branch: the file's bytes could not be read at all, so no repair is attempted.","triggerScenarios":"load_jobs() finds jobs.json exists but open()/read() raises OSError: file owned by another user with mode 600, a read-only or full filesystem, the file being a directory, or a transient NFS/FUSE error. Any cron operation (list/create/save via hermes cron, the cronjob tool, the scheduler tick) that loads jobs hits it.","commonSituations":"Running `hermes cron` under sudo previously so jobs.json is root-owned; disk full; the HERMES_HOME/profile directory was restored from a backup with wrong ownership; two profiles pointed at the same home with different users.","solutions":["Check the underlying IOError in the message, then inspect permissions on jobs.json and its parent directory.","Fix ownership/permissions: chown/chmod the file so the current user can read AND write it (cron also saves).","Free disk space or remount a read-only filesystem read-write.","If the file is a directory or otherwise mangled, move it aside and let cron recreate an empty jobs list."],"exampleFix":"# shell — before: cron commands fail with 'Failed to read cron database'\nls -la ~/.hermes/cron/jobs.json   # owned by root:root\n\n# after\nsudo chown -R \"$USER\" ~/.hermes/cron && hermes cron list","handlingStrategy":"try-catch","validationCode":"from pathlib import Path\nfrom hermes_constants import get_hermes_home\n\njobs_file = get_hermes_home() / \"cron\" / \"jobs.json\"\nif jobs_file.exists() and not jobs_file.is_file():\n    raise SystemExit(\"jobs.json is not a regular file\")\nif jobs_file.exists():\n    try:\n        jobs_file.read_text()\n    except OSError as e:\n        raise SystemExit(f\"jobs.json unreadable: {e} — fix permissions first\")","typeGuard":null,"tryCatchPattern":"from cron.jobs import list_jobs\ntry:\n    jobs = list_jobs()\nexcept RuntimeError as e:\n    if \"Failed to read cron database\" in str(e):\n        # IO problem: check ownership/permissions of jobs.json, free disk, then retry after fix\n        raise","preventionTips":["Never run `hermes cron` commands under sudo — root-owned jobs.json breaks later runs.","Keep ~/.hermes/cron writable by the user that runs the gateway; monitor disk space."],"tags":["cron","ioerror","filesystem","permissions","runtimeerror"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}