{"record":{"id":"0ea577420a254cdc","repo":"NousResearch/hermes-agent","slug":"no-install-root","errorCode":null,"errorMessage":"no install root","messagePattern":"no install root","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/bootstrap-installer/src/store.ts","lineNumber":354,"sourceCode":"  $route.set('progress')\n  await invoke('start_update')\n}\n\nexport async function cancelInstall(): Promise<void> {\n  if (fakeMode()) {\n    fakeCancelled = true\n\n    return\n  }\n\n  await invoke('cancel_bootstrap')\n}\n\nexport async function launchHermesDesktop(): Promise<void> {\n  if (fakeMode()) {throw new Error('Preview mode — launching is disabled.')}\n  const installRoot = $bootstrap.get().installRoot\n\n  if (!installRoot) {throw new Error('no install root')}\n  await invoke('launch_hermes_desktop', { installRoot })\n}\n\nexport async function openLogDir(): Promise<void> {\n  if (fakeMode()) {return}\n  await invoke('open_log_dir')\n}\n\n// ---------------------------------------------------------------------------\n// Dev-only isolated preview (\"fake boot\")\n//\n// Synthesises the manifest + stage/log events Rust normally streams, so the\n// whole reskin can be reviewed in a plain browser (`npm run dev`):\n//   ?fake=install   welcome → [ INSTALL ] → success\n//   ?fake=update    auto-runs the granular update flow\n//   ?fake=failure   install that fails partway\n// Gated on import.meta.env.DEV → stripped from the shipped Tauri bundle.\n// ---------------------------------------------------------------------------","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/bootstrap-installer/src/store.ts#L336-L372","documentation":"Terminal ValueError from the schedule parser in cron/jobs.py (parse_schedule): every supported format — 'every ...' interval, cron expression, ISO timestamp, and plain duration — failed to match. The message enumerates the four accepted forms, so the input matched none of them. Nothing is persisted; this is pure input validation.","triggerScenarios":"Calling create_job / update_job / `hermes cron add` with strings like 'tomorrow', 'every monday at nine', '30 min' (space inside duration), '9am daily', or an empty/garbage schedule. Also cron strings with the wrong field count fall through to here.","commonSituations":"Natural-language schedules from an LLM that were never normalized, duration strings with units the parser doesn't know ('1w', '30s' if unsupported), or a user assuming a 6-field cron expression is accepted.","solutions":["Use one of the four documented forms: duration '30m'/'2h'/'1d', interval 'every 30m'/'every monday 9am', 5-field cron '0 9 * * *', or ISO timestamp '2026-02-03T14:00:00'.","Check for stray whitespace/quotes around the string before submitting.","Verify cron expressions have exactly 5 space-separated fields.","If generating schedules from model output, pre-validate against the four patterns and re-ask on failure."],"exampleFix":"# before\ncreate_job(prompt=\"digest\", schedule=\"every day at 9\")\n\n# after\ncreate_job(prompt=\"digest\", schedule=\"every day 9am\")  # or \"0 9 * * *\"","handlingStrategy":"validation","validationCode":"import re\nfrom datetime import datetime\n\ndef looks_like_valid_schedule(s: str) -> bool:\n    s = s.strip()\n    if re.fullmatch(r\"\\d+[mhd]\", s): return True                    # duration\n    if s.lower().startswith(\"every \"): return True                  # interval\n    if len(s.split()) == 5 and re.fullmatch(r\"[\\d*/,-]+( [\\d*/,-]+){4}\", s): return True  # cron\n    try:\n        datetime.fromisoformat(s); return True                      # timestamp\n    except ValueError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    job = create_job(prompt=p, schedule=schedule)\nexcept ValueError as e:\n    if \"Invalid schedule\" in str(e):\n        # show the four accepted formats to the caller/model and retry once\n        raise","preventionTips":["Normalize natural-language schedules ('every day at 9') into one of the four machine forms before submission.","Validate cron expressions have exactly 5 fields and duration strings match \\d+[mhd]."],"tags":["cron","schedule","validation","valueerror"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}