{"record":{"id":"2916a0f0aed13571","repo":"Yeachan-Heo/oh-my-codex","slug":"max-injections-per-session-must-be-1","errorCode":null,"errorMessage":"`max_injections_per_session` must be >= 1","messagePattern":"`max_injections_per_session` must be >= 1","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/tmux-hook.ts","lineNumber":140,"sourceCode":"  if (targetObj.type !== 'session' && targetObj.type !== 'pane') {\n    throw new Error('`target.type` must be \"session\" or \"pane\"');\n  }\n  if (typeof targetObj.value !== 'string' || targetObj.value.trim() === '') {\n    throw new Error('`target.value` must be a non-empty string');\n  }\n\n  const allowedModes = parsed.allowed_modes;\n  if (!Array.isArray(allowedModes) || allowedModes.length === 0 || allowedModes.some(v => typeof v !== 'string')) {\n    throw new Error('`allowed_modes` must be a non-empty string array');\n  }\n\n  const cooldown = parsed.cooldown_ms;\n  const maxInjections = parsed.max_injections_per_session;\n  if (typeof cooldown !== 'number' || cooldown < 0 || !Number.isFinite(cooldown)) {\n    throw new Error('`cooldown_ms` must be a non-negative number');\n  }\n  if (typeof maxInjections !== 'number' || maxInjections < 1 || !Number.isFinite(maxInjections)) {\n    throw new Error('`max_injections_per_session` must be >= 1');\n  }\n\n  const promptTemplate = parsed.prompt_template;\n  const marker = parsed.marker;\n  if (typeof promptTemplate !== 'string' || promptTemplate.trim() === '') {\n    throw new Error('`prompt_template` must be a non-empty string');\n  }\n  if (typeof marker !== 'string' || marker.trim() === '') {\n    throw new Error('`marker` must be a non-empty string');\n  }\n\n  if (parsed.dry_run !== true && parsed.dry_run !== false) {\n    throw new Error('`dry_run` must be boolean');\n  }\n  if (parsed.log_level !== 'error' && parsed.log_level !== 'info' && parsed.log_level !== 'debug') {\n    throw new Error('`log_level` must be one of: error, info, debug');\n  }\n  if (parsed.skip_if_scrolling !== undefined && parsed.skip_if_scrolling !== true && parsed.skip_if_scrolling !== false) {","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/tmux-hook.ts#L122-L158","documentation":"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.","triggerScenarios":"\"max_injections_per_session\": 0, negative values, string values, or the key omitted so it is undefined.","commonSituations":"Users setting 0 intending 'unlimited' (not supported); string numbers from templating; missing key in hand-written configs.","solutions":["Set a value >= 1, e.g. \"max_injections_per_session\": 5","Pick a larger number rather than 0 for a loose cap","Regenerate the config with omx tmux-hook init"],"exampleFix":"// before\n{\"max_injections_per_session\": 0}\n// after\n{\"max_injections_per_session\": 10}","handlingStrategy":"validation","validationCode":"const m = cfg.max_injections_per_session;\nif (typeof m !== 'number' || m < 1 || !Number.isFinite(m)) throw new Error('bad max_injections_per_session');","typeGuard":"const isPositiveFiniteInt = (v: unknown): v is number => typeof v === 'number' && v >= 1 && Number.isFinite(v);","tryCatchPattern":"try { await loadConfig(); } catch (e) { if (e instanceof Error && e.message.includes('max_injections')) fixCap(); }","preventionTips":["0 does not mean unlimited; use a large number instead","Keep the key present with a value >= 1"],"tags":["config","validation","numeric","tmux-hook"],"backgroundTag":"config-schema-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}