Yeachan-Heo/oh-my-codex · error · Error

authority state cooldown_ms must be a non-negative number

Error message

authority state cooldown_ms must be a non-negative number

What it means

This error is thrown by validateAuthorityState in the HUD authority module when the persisted authority state file contains a cooldown_ms field that is not a finite non-negative number. The validator runs on every read of the authority state, so any corruption or hand-editing of the state file surfaces here. It protects the rate-limiting cooldown computation from NaN/negative values.

Source

Thrown at src/hud/authority.ts:154

function isAuthorityStatus(value: unknown): value is HudAuthorityState['last_status'] {
  return value === 'spawned' || value === 'skipped' || value === 'failed' || value === 'locked';
}

function validateAuthorityState(value: unknown): HudAuthorityState {
  if (typeof value !== 'object' || value === null) {
    throw new Error('authority state must be an object');
  }
  const state = value as Partial<HudAuthorityState>;
  if (state.owner !== 'hud') throw new Error('authority state owner must be hud');
  if (typeof state.pid !== 'number' || !Number.isInteger(state.pid) || state.pid <= 0) {
    throw new Error('authority state pid must be a positive integer');
  }
  if (typeof state.cwd !== 'string' || !state.cwd) throw new Error('authority state cwd must be a non-empty string');
  if (parseIsoMs(state.heartbeat_at) === null) throw new Error('authority state heartbeat_at must be a valid ISO timestamp');
  if (parseIsoMs(state.next_allowed_at) === null) throw new Error('authority state next_allowed_at must be a valid ISO timestamp');
  if (typeof state.cooldown_ms !== 'number' || !Number.isFinite(state.cooldown_ms) || state.cooldown_ms < 0) {
    throw new Error('authority state cooldown_ms must be a non-negative number');
  }
  if (typeof state.jitter_ms !== 'number' || !Number.isFinite(state.jitter_ms) || state.jitter_ms < 0) {
    throw new Error('authority state jitter_ms must be a non-negative number');
  }
  if (typeof state.skip_count !== 'number' || !Number.isInteger(state.skip_count) || state.skip_count < 0) {
    throw new Error('authority state skip_count must be a non-negative integer');
  }
  if (!isAuthorityStatus(state.last_status)) throw new Error('authority state last_status is invalid');
  if (typeof state.last_reason !== 'string' || !state.last_reason) {
    throw new Error('authority state last_reason must be a non-empty string');
  }
  return state as HudAuthorityState;
}

async function readAuthorityState(path: string): Promise<HudAuthorityState | null> {
  try {
    return validateAuthorityState(JSON.parse(await readFile(path, 'utf-8')));
  } catch (error) {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Inspect the authority state JSON file and fix cooldown_ms to a non-negative finite number (e.g. 0)
  2. Delete the authority state file so it is recreated with defaults
  3. Ensure only one version of the tool writes the state file (no version mixing)
  4. Check for concurrent writers racing on the state file

Example fix

// before: state file contains "cooldown_ms": "1000"
// after: state file contains "cooldown_ms": 1000
Defensive patterns

Strategy: validation

Validate before calling

const s = JSON.parse(fs.readFileSync(authorityStatePath,'utf8'));
if (typeof s.cooldown_ms !== 'number' || !Number.isFinite(s.cooldown_ms) || s.cooldown_ms < 0) {
  // repair or reset state before running the tick
}

Type guard

function isValidAuthorityState(s: any): s is { cooldown_ms: number } {
  return typeof s?.cooldown_ms === 'number' && Number.isFinite(s.cooldown_ms) && s.cooldown_ms >= 0;
}

Try / catch

catch (e) { if ((e as Error).message.includes('cooldown_ms')) { /* reset state file and retry once */ } else throw e; }

Prevention

When it happens

Trigger: readAuthorityState parses the authority state JSON and its cooldown_ms is a string, NaN, Infinity, a negative number, or missing/mis-typed after manual editing or a partially written file. Called from runHudAuthorityTick during tick processing.

Common situations: Hand-edited .omx state files, state written by an older version with a different schema, disk corruption or truncated JSON writes, or external tooling writing the state file with stringified numbers.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/73c38ef34b6172f9. Report an issue: GitHub.