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

`marker` must be a non-empty string

Error message

`marker` must be a non-empty string

What it means

The config's marker must be a non-empty string; it is the sentinel marker the hook uses to tag/detect injected content. Empty, whitespace-only, non-string, or missing values fail.

Source

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

    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) {
    throw new Error('`skip_if_scrolling` must be boolean');
  }

  return {
    enabled: parsed.enabled,
    target: { type: targetObj.type, value: targetObj.value },
    allowed_modes: allowedModes,
    cooldown_ms: cooldown,
    max_injections_per_session: maxInjections,

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Set a distinctive non-empty marker string, e.g. "__OMX_INJECT__"
  2. Avoid markers that collide with normal shell output
  3. Regenerate config with omx tmux-hook init for the default value

Example fix

// before
{"marker": ""}
// after
{"marker": "__OMX_HOOK__"}
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof cfg.marker !== 'string' || cfg.marker.trim() === '') throw new Error('bad marker');

Type guard

const isNonEmptyString = (v: unknown): v is string => typeof v === 'string' && v.trim() !== '';

Try / catch

try { await loadConfig(); } catch (e) { if (e instanceof Error && e.message.includes('`marker`')) fixMarker(); }

Prevention

When it happens

Trigger: "marker": "", " ", numeric values, or the key omitted entirely.

Common situations: Assuming a default marker exists; wiping the field during edits; marker keys renamed between versions.

Related errors


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