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

`max_injections_per_session` must be >= 1

Error message

`max_injections_per_session` must be >= 1

What it means

The config's max_injections_per_session must be a finite number >= 1, capping how many times the hook injects per session. 0, negatives, non-numbers, NaN, or Infinity all fail.

Source

Thrown at src/cli/tmux-hook.ts:140

  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') {
    throw new Error('`log_level` must be one of: error, info, debug');
  }
  if (parsed.skip_if_scrolling !== undefined && parsed.skip_if_scrolling !== true && parsed.skip_if_scrolling !== false) {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Set a value >= 1, e.g. "max_injections_per_session": 5
  2. Pick a larger number rather than 0 for a loose cap
  3. Regenerate the config with omx tmux-hook init

Example fix

// before
{"max_injections_per_session": 0}
// after
{"max_injections_per_session": 10}
Defensive patterns

Strategy: validation

Validate before calling

const m = cfg.max_injections_per_session;
if (typeof m !== 'number' || m < 1 || !Number.isFinite(m)) throw new Error('bad max_injections_per_session');

Type guard

const isPositiveFiniteInt = (v: unknown): v is number => typeof v === 'number' && v >= 1 && Number.isFinite(v);

Try / catch

try { await loadConfig(); } catch (e) { if (e instanceof Error && e.message.includes('max_injections')) fixCap(); }

Prevention

When it happens

Trigger: "max_injections_per_session": 0, negative values, string values, or the key omitted so it is undefined.

Common situations: Users setting 0 intending 'unlimited' (not supported); string numbers from templating; missing key in hand-written configs.

Related errors


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