NousResearch/hermes-agent · error

Could not generate a valid desktop installation ID.

Error message

Could not generate a valid desktop installation ID.

What it means

ValueError from update_job (cron/jobs.py:1952): the update changed the job's schedule to a 'once' kind whose run_at is more than ONESHOT_GRACE_SECONDS (120s) in the past (compute_next_run returned None). Same guard as creation, applied through the update door so an existing job can't be pushed into a state where it would never fire.

Source

Thrown at apps/desktop/electron/desktop-installation.ts:55

}

function waitForRepair() {
  const buffer = new SharedArrayBuffer(4)
  Atomics.wait(new Int32Array(buffer), 0, 0, 25)
}

function loadOrCreateInstallationId(filePath, randomUUID = crypto.randomUUID) {
  const existing = readInstallationId(filePath)

  if (existing) {
    return existing
  }

  fs.mkdirSync(path.dirname(filePath), { recursive: true })
  const installationId = randomUUID().toLowerCase()

  if (!INSTALLATION_ID_RE.test(installationId)) {
    throw new Error('Could not generate a valid desktop installation ID.')
  }

  const repairPath = `${filePath}.repair.lock`

  for (let attempt = 0; attempt < 40; attempt++) {
    let repairFd

    try {
      repairFd = fs.openSync(repairPath, 'wx', 0o600)
    } catch (error: any) {
      if (error?.code !== 'EEXIST') {
        throw error
      }

      const winner = readInstallationId(filePath)

      if (winner) {
        return winner

View on GitHub (pinned to c896c09c42)

Solutions

  1. Set the new schedule to a future timestamp or a relative duration like '45m'.
  2. If you meant to reschedule a missed run, compute now + delta rather than reusing the old time.
  3. Verify the scheduler host's clock/timezone if the timestamp 'looks future' to you.

Example fix

# before
update_job(job_id, {"schedule": "2026-08-14T09:00"})  # past

# after
update_job(job_id, {"schedule": "2h"})  # one-shot two hours from now
Defensive patterns

Strategy: validation

Validate before calling

from datetime import datetime, timedelta

def future_schedule(s: str) -> bool:
    if not s or s[0].isdigit() and "T" in s:
        try:
            return datetime.fromisoformat(s) > datetime.now() + timedelta(minutes=5)
        except ValueError:
            return False
    return True  # durations/intervals/cron are computed from now

Try / catch

try:
    update_job(job_id, {"schedule": new_sched})
except ValueError as e:
    if "in the past" in str(e):
        update_job(job_id, {"schedule": "1h"})  # reschedule relative to now
        raise

Prevention

When it happens

Trigger: update_job(id, {'schedule': '2026-01-01T09:00'}) with a past timestamp; editing the schedule of a paused one-shot job whose time has since passed; clock skew between the client and scheduler host.

Common situations: Postponing a missed one-shot by nudging the schedule but picking an already-elapsed time; copy-pasting an old timestamp; editing on a machine whose clock/timezone differs from the gateway.

Related errors


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