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

${fieldName} contains invalid task ID: "${item}"

Error message

${fieldName} contains invalid task ID: "${item}"

What it means

Thrown when a task ID string inside an array fails TASK_ID_SAFE_PATTERN after trimming (digits-only positive integer, max 20 digits). The library rejects IDs containing non-digit characters to keep CLI interop shell-safe.

Source

Thrown at src/team/api-interop.ts:453

      snapshot_available: snapshot !== null,
      phase_available: phaseState !== null,
      recent_event_count: recentEvents.length,
    },
  };
}

function parseValidatedTaskIdArray(value: unknown, fieldName: string): string[] {
  if (!Array.isArray(value)) {
    throw new Error(`${fieldName} must be an array of task IDs (strings)`);
  }
  const taskIds: string[] = [];
  for (const item of value) {
    if (typeof item !== 'string') {
      throw new Error(`${fieldName} entries must be strings`);
    }
    const normalized = item.trim();
    if (!TASK_ID_SAFE_PATTERN.test(normalized)) {
      throw new Error(`${fieldName} contains invalid task ID: "${item}"`);
    }
    taskIds.push(normalized);
  }
  return taskIds;
}

function teamStateExists(teamName: string, candidateCwd: string): boolean {
  if (!TEAM_NAME_SAFE_PATTERN.test(teamName)) return false;
  const teamRoot = join(resolveCanonicalTeamStateRoot(candidateCwd), 'team', teamName);
  return existsSync(join(teamRoot, 'config.json')) || existsSync(join(teamRoot, 'tasks')) || existsSync(teamRoot);
}

function readTeamStateRootFromManifest(path: string): string | null {
  if (!existsSync(path)) return null;
  try {
    const parsed = JSON.parse(readFileSync(path, 'utf8')) as { team_state_root?: unknown };
    return typeof parsed.team_state_root === 'string' && parsed.team_state_root.trim() !== ''
      ? parsed.team_state_root.trim()

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Strip non-digit prefixes/suffixes before passing IDs
  2. Verify each ID matches /^\d{1,20}$/ (non-zero-leading positive integers if required)
  3. Re-fetch canonical task IDs from the team API instead of constructing them manually

Example fix

// before
api('update-tasks', { task_ids: ['TASK-42'] });
// after
api('update-tasks', { task_ids: ['42'] });
Defensive patterns

Strategy: type-guard

Validate before calling

const TASK_ID = /^\d{1,20}$/;
const valid = ids.every((id) => TASK_ID.test(id.trim()));
if (!valid) throw new RangeError('task ids must be 1-20 digit integers');

Type guard

const isSafeTaskId = (id: string): boolean => /^\d{1,20}$/.test(id.trim());

Try / catch

catch (e) { if (e instanceof Error && e.message.includes('invalid task ID')) { /* log offending field, re-prompt */ } throw e; }

Prevention

When it happens

Trigger: Passing task IDs like 'abc', '#12', '12.5', ' ' (empty after trim), or IDs longer than 20 digits within a task ID array field.

Common situations: Copying IDs from an external tracker that includes prefixes (e.g. 'TASK-42'); trailing whitespace or unicode digits; using a UUID as a task ID.

Related errors


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