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
- Strip non-digit prefixes/suffixes before passing IDs
- Verify each ID matches /^\d{1,20}$/ (non-zero-leading positive integers if required)
- 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
- Never forward prefixed IDs from external trackers without normalization
- Unit-test ID normalization against the same regex
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
- Invalid task_id: "${rawTaskId}". Must be a positive integer
- ${fieldName} entries must be strings
- Invalid task ID: "${taskId}". Must be a positive integer (di
- invalid auth slot path
- Autoresearch goal ${mission.slug} cannot complete until prof
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/38a165c5886de532.
Report an issue: GitHub.