Yeachan-Heo/oh-my-codex · error · Error
`cooldown_ms` must be a non-negative number
Error message
`cooldown_ms` must be a non-negative number
What it means
The config's cooldown_ms field must be a number that is finite and >= 0 (throttle between hook injections). NaN, Infinity, negatives, strings, or missing values fail.
Source
Thrown at src/cli/tmux-hook.ts:137
throw new Error('`target` is required');
}
const targetObj = target as Record<string, unknown>;
if (targetObj.type !== 'session' && targetObj.type !== 'pane') {
throw new Error('`target.type` must be "session" or "pane"');
}
if (typeof targetObj.value !== 'string' || targetObj.value.trim() === '') {
throw new Error('`target.value` must be a non-empty string');
}
const allowedModes = parsed.allowed_modes;
if (!Array.isArray(allowedModes) || allowedModes.length === 0 || allowedModes.some(v => typeof v !== 'string')) {
throw new Error('`allowed_modes` must be a non-empty string array');
}
const cooldown = parsed.cooldown_ms;
const maxInjections = parsed.max_injections_per_session;
if (typeof cooldown !== 'number' || cooldown < 0 || !Number.isFinite(cooldown)) {
throw new Error('`cooldown_ms` must be a non-negative number');
}
if (typeof maxInjections !== 'number' || maxInjections < 1 || !Number.isFinite(maxInjections)) {
throw new Error('`max_injections_per_session` must be >= 1');
}
const promptTemplate = parsed.prompt_template;
const marker = parsed.marker;
if (typeof promptTemplate !== 'string' || promptTemplate.trim() === '') {
throw new Error('`prompt_template` must be a non-empty string');
}
if (typeof marker !== 'string' || marker.trim() === '') {
throw new Error('`marker` must be a non-empty string');
}
if (parsed.dry_run !== true && parsed.dry_run !== false) {
throw new Error('`dry_run` must be boolean');
}
if (parsed.log_level !== 'error' && parsed.log_level !== 'info' && parsed.log_level !== 'debug') {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Set a non-negative finite number, e.g. "cooldown_ms": 1000
- Coerce with Number(...) and validate before writing templated configs
- Use 0 if you want no cooldown
Example fix
// before
{"cooldown_ms": "1000"}
// after
{"cooldown_ms": 1000} Defensive patterns
Strategy: validation
Validate before calling
const c = cfg.cooldown_ms;
if (typeof c !== 'number' || c < 0 || !Number.isFinite(c)) throw new Error('bad cooldown_ms'); Type guard
const isNonNegativeFinite = (v: unknown): v is number => typeof v === 'number' && v >= 0 && Number.isFinite(v);
Try / catch
try { await loadConfig(); } catch (e) { if (e instanceof Error && e.message.includes('cooldown_ms')) fixCooldown(); } Prevention
- Write numbers unquoted in JSON
- Coerce env-var strings with Number() and validate before templating
When it happens
Trigger: "cooldown_ms": -100, "cooldown_ms": "1000", omitted key (undefined), or a computed value producing NaN.
Common situations: String numbers from env-var templating; zero-default assumptions; arithmetic on user input producing NaN.
Related errors
- `max_injections_per_session` must be >= 1
- tmux-hook config must be a JSON object
- `enabled` must be boolean
- `target` is required
- `target.type` must be "session" or "pane"
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/1d61e9d9ce7f3817.
Report an issue: GitHub.