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

`target.type` must be "session" or "pane"

Error message

`target.type` must be "session" or "pane"

What it means

The config's target.type field must be exactly the string "session" or "pane"; anything else (including missing/undefined, capitalized forms, or plurals) is rejected.

Source

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

function tmuxHookLogPath(cwd = process.cwd()): string {
  return join(omxDir(cwd), 'logs', `tmux-hook-${new Date().toISOString().split('T')[0]}.jsonl`);
}

function parseConfig(raw: unknown): TmuxHookConfig {
  if (!raw || typeof raw !== 'object') {
    throw new Error('tmux-hook config must be a JSON object');
  }
  const parsed = raw as Record<string, unknown>;
  if (parsed.enabled !== true && parsed.enabled !== false) {
    throw new Error('`enabled` must be boolean');
  }
  const target = parsed.target;
  if (!target || typeof target !== 'object') {
    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');
  }

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Use exactly "session" or "pane" (lowercase)
  2. Pick pane if you want injection into a specific pane id like %3
  3. Re-read the supported target types via omx tmux-hook help

Example fix

// before
{"target": {"type": "window", "value": "0"}}
// after
{"target": {"type": "session", "value": "omx"}}
Defensive patterns

Strategy: validation

Validate before calling

const t = cfg.target?.type;
if (t !== 'session' && t !== 'pane') throw new Error('bad target.type');

Type guard

const isTargetType = (v: unknown): v is 'session' | 'pane' => v === 'session' || v === 'pane';

Try / catch

try { await loadConfig(); } catch (e) { if (e instanceof Error && e.message.includes('target.type')) fixType(); }

Prevention

When it happens

Trigger: "type": "window", "type": "Session", or omitting type so it is undefined.

Common situations: Users guessing the tmux terminology (tmux has windows/sessions/panes and only two are supported); case or spelling mistakes.

Related errors


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