Yeachan-Heo/oh-my-codex · error · Error
Invalid task_id: "${rawTaskId}". Must be a positive integer
Error message
Invalid task_id: "${rawTaskId}". Must be a positive integer (digits only, max 20 digits). What it means
validateCommonFields throws this when a non-empty task_id fails TASK_ID_SAFE_PATTERN — it must be a digits-only positive integer of at most 20 digits. This guards shell interop from injection and malformed references.
Source
Thrown at src/team/api-interop.ts:581
return `Use CLI interop: omx team api ${operation} --input '${payload}' --json`;
}
function validateCommonFields(args: Record<string, unknown>, options: { skipTeamName?: boolean } = {}): void {
const teamName = String(args.team_name || '').trim();
if (!options.skipTeamName && teamName && !TEAM_NAME_SAFE_PATTERN.test(teamName)) {
throw new Error(`Invalid team_name: "${teamName}". Must match /^[a-z0-9][a-z0-9-]{0,29}$/ (lowercase alphanumeric + hyphens, max 30 chars).`);
}
for (const workerField of ['worker', 'from_worker', 'to_worker']) {
const workerVal = String(args[workerField] || '').trim();
if (workerVal && !WORKER_NAME_SAFE_PATTERN.test(workerVal)) {
throw new Error(`Invalid ${workerField}: "${workerVal}". Must match /^[a-z0-9][a-z0-9-]{0,63}$/ (lowercase alphanumeric + hyphens, max 64 chars).`);
}
}
const rawTaskId = String(args.task_id || '').trim();
if (rawTaskId && !TASK_ID_SAFE_PATTERN.test(rawTaskId)) {
throw new Error(`Invalid task_id: "${rawTaskId}". Must be a positive integer (digits only, max 20 digits).`);
}
}
function normalizeTeamDisplayLookupName(value: string): string {
return value
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '')
.slice(0, 30)
.replace(/-$/, '');
}
function assertUnsafeTeamNameMatchesKnownDisplay(rawTeamName: string, cwd: string): void {
if (TEAM_NAME_SAFE_PATTERN.test(rawTeamName)) return;
const normalized = normalizeTeamDisplayLookupName(rawTeamName);
const matchesKnownDisplay = listTeamLookupCandidates(cwd).some((candidate) => {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Extract only the digit portion of the ID before the call
- Confirm the value is a plain integer string (no sign, no exponent)
- If the ID comes from another system, map it to the team task ID first
Example fix
// before
api('get-task', { task_id: 'task-12' });
// after
api('get-task', { task_id: '12' }); Defensive patterns
Strategy: validation
Validate before calling
const TASK_ID = /^\d{1,20}$/;
const id = String(args.task_id || '').trim();
if (id && !TASK_ID.test(id)) throw new RangeError('task_id must be digits (max 20)'); Type guard
const isSafeTaskId = (id: string): boolean => /^\d{1,20}$/.test(id); Prevention
- Strip prefixes like 'TASK-' at ingestion boundaries
- Never pass floats or exponent notation as task IDs
When it happens
Trigger: Passing task_id such as '12a', 'task-12', '-5', '1e3', or a 25-digit string in the args object.
Common situations: Forwarding IDs from URLs or tickets with prefixes; scientific notation from a JSON serializer; extremely long numeric IDs from external systems.
Related errors
- ${fieldName} contains invalid task ID: "${item}"
- ${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/d7d3a6e9ef61fd15.
Report an issue: GitHub.