{"record":{"id":"1eb8493e96862e7d","repo":"NousResearch/hermes-agent","slug":"cannot-resolve-installscriptname-no-source-r","errorCode":null,"errorMessage":"Cannot resolve ${installScriptName()}: no SOURCE_REPO_ROOT and no install stamp. This packaged build was produced without a valid build-time stamp.","messagePattern":"Cannot resolve (.+?): no SOURCE_REPO_ROOT and no install stamp\\. This packaged build was produced without a valid build-time stamp\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"apps/desktop/electron/bootstrap-runner.ts","lineNumber":341,"sourceCode":"}) {\n  // 1. Dev shortcut: prefer a local checkout's installer so we can iterate\n  //    without pushing. SOURCE_REPO_ROOT comes from main.ts (path.resolve\n  //    of APP_ROOT/../..).\n  const localScript = resolveLocalInstallScript(sourceRepoRoot)\n\n  if (localScript) {\n    emit({ type: 'log', line: `[bootstrap] using local ${installScriptName()} at ${localScript}` })\n\n    return { path: localScript, source: 'local', kind: installScriptKind() }\n  }\n\n  // 2. Packaged path: download from GitHub at the install stamp's ref.\n  // Non-git fallback builds carry an all-zero commit; treat that as an\n  // unpinned branch ref instead of trying to fetch a non-existent SHA.\n  const installRef = installRefForStamp(installStamp)\n\n  if (!installRef) {\n    throw new Error(\n      `Cannot resolve ${installScriptName()}: no SOURCE_REPO_ROOT and no install stamp. ` +\n        'This packaged build was produced without a valid build-time stamp.'\n    )\n  }\n\n  const cached = cachedScriptPath(hermesHome, installRef.cacheKey)\n  const resolvedCommit = installRef.pinned ? installRef.ref : null\n\n  try {\n    await fsp.access(cached, fs.constants.R_OK)\n    emit({\n      type: 'log',\n      line: `[bootstrap] using cached ${installScriptName()} for ${installRef.ref.slice(0, 12)}`\n    })\n\n    return { path: cached, source: 'cache', commit: resolvedCommit, kind: installScriptKind() }\n  } catch {\n    // not cached; download","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/electron/bootstrap-runner.ts#L323-L359","documentation":"RuntimeError from load_jobs() (cron/jobs.py:1097): _parse_jobs_file() tried its strict-then-repair JSON parse and a non-IO exception escaped, meaning the file is corrupt beyond what auto-repair handles (control-character escaping, bare-list wrapping). The cron subsystem deliberately fails closed rather than silently discarding user jobs.","triggerScenarios":"jobs.json truncated mid-write by a crash/power loss, hand-edited into invalid JSON that the repair passes can't fix, binary garbage from a bad sync tool, or a file whose top-level JSON parses but whose repair path itself raises (e.g. exotic encoding issues).","commonSituations":"Editing jobs.json manually and introducing a syntax error; an interrupted write because the machine died mid-save; a sync tool (Dropbox/backup restore) writing a partial file.","solutions":["Back up the corrupt file: cp ~/.hermes/cron/jobs.json{,.bak}.","Inspect it (python -m json.tool) to find the damage; often only a trailing fragment needs deleting.","Repair the JSON by hand or rebuild the file as {\"jobs\": [...]} from the readable parts.","If unrecoverable, move the file aside — load_jobs treats a missing file as empty and `hermes cron add` recreates it; re-add your jobs from the backup text."],"exampleFix":"# before: jobs.json ends with '{\"jobs\": [{\"id\": \"j1\", \"prom'\n# after: valid JSON, then reload\npython -m json.tool ~/.hermes/cron/jobs.json   # locate the error\n# fix or replace with {\"jobs\": []}, then: hermes cron list","handlingStrategy":"fallback","validationCode":"import json\nfrom pathlib import Path\nfrom hermes_constants import get_hermes_home\n\nf = get_hermes_home() / \"cron\" / \"jobs.json\"\nif f.exists():\n    try:\n        json.loads(f.read_text())\n    except (json.JSONDecodeError, UnicodeDecodeError):\n        print(\"jobs.json is corrupt — back it up before Hermes loads it: cp\", f, f.with_suffix('.json.bak'))","typeGuard":null,"tryCatchPattern":"from cron.jobs import list_jobs\nimport shutil\ntry:\n    jobs = list_jobs()\nexcept RuntimeError as e:\n    if \"corrupted and unrepairable\" in str(e):\n        shutil.copy2(f, f.with_suffix(\".json.corrupt\"))  # preserve salvageable text\n        f.write_text('{\"jobs\": []}')                     # reset store, re-add jobs after\n        jobs = list_jobs()","preventionTips":["Don't hand-edit jobs.json; use `hermes cron add/edit/remove`.","Exclude jobs.json from tools that can write partial files (atomic-sync only), and keep backups of ~/.hermes/cron."],"tags":["cron","json","corruption","runtimeerror"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}