Yeachan-Heo/oh-my-codex · error · Error
Invalid task ID: "${taskId}". Must be a positive integer (di
Error message
Invalid task ID: "${taskId}". Must be a positive integer (digits only, max 20 digits). What it means
Task ID failed TASK_ID_SAFE_PATTERN: it must be a positive integer expressed as digits only, at most 20 digits (no signs, decimals, or non-numeric characters). Thrown by validateTaskId via taskClaimLockDir, approvalPath, and taskFilePath.
Source
Thrown at src/team/state.ts:508
function assertPathWithinDir(filePath: string, rootDir: string): void {
const normalizedRoot = resolve(rootDir);
const normalizedPath = resolve(filePath);
if (normalizedPath !== normalizedRoot && !normalizedPath.startsWith(normalizedRoot + sep)) {
throw new Error('Path traversal detected: path is outside the allowed directory');
}
}
function validateWorkerName(name: string): void {
if (!WORKER_NAME_SAFE_PATTERN.test(name)) {
throw new Error(
`Invalid worker name: "${name}". Must match /^[a-z0-9][a-z0-9-]{0,63}$/ (lowercase alphanumeric + hyphens, max 64 chars).`
);
}
}
function validateTaskId(taskId: string): void {
if (!TASK_ID_SAFE_PATTERN.test(taskId)) {
throw new Error(
`Invalid task ID: "${taskId}". Must be a positive integer (digits only, max 20 digits).`
);
}
}
function defaultLeader(): TeamLeader {
return {
session_id: '',
worker_id: 'leader-fixed',
role: 'coordinator',
};
}
function defaultTmuxPaneOwnerId(teamName: string): string {
return `team:${teamName}`;
}
function defaultPolicy(View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Extract the numeric portion (e.g. parseInt/regex '^\\d+$') and pass it as a canonical decimal string
- Validate ids at input boundaries with /^\d{1,20}$/ before calling these APIs
- Reject or remap non-numeric external identifiers instead of passing them through
Example fix
// before
const p = taskFilePath(`task-${id}`, ...); // throws
// after
const numericId = String(id).replace(/^\D+/, '');
if (!/^\d{1,20}$/.test(numericId)) throw new Error('invalid task id');
const p = taskFilePath(numericId, ...); Defensive patterns
Strategy: type-guard
Validate before calling
function normalizeTaskId(raw: string | number): string | null {
const s = typeof raw === 'number' ? String(Math.trunc(raw)) : raw;
return /^\d{1,20}$/.test(s) && !/^0/.test(s) === false ? (s === '0' ? null : s) : (/^[1-9]\d{0,19}$/.test(s) ? s : null);
} Type guard
function isValidTaskId(taskId: string): boolean {
return /^[1-9]\d{0,19}$|^0$/.test(taskId) && /^\d{1,20}$/.test(taskId);
} Prevention
- Map external UUIDs to numeric task ids at the integration layer
- Parse ids with strict numeric regex before calling task state APIs
When it happens
Trigger: Passing task ids like 'task-12', '12.0', '-5', a UUID, or an empty string to taskClaimLockDir, approvalPath, or taskFilePath.
Common situations: External systems using UUID or prefixed ids mapped directly to task ids; parsing ids from strings without stripping prefixes; numeric ids serialized as floats.
Related errors
- Invalid worker name: "${name}". Must match /^[a-z0-9][a-z0-9
- ${fieldName} contains invalid task ID: "${item}"
- Invalid task_id: "${rawTaskId}". Must be a positive integer
- approved_execution_binding_malformed:${sanitized}
- scale_down_cleanup_debt_invalid_team_state_root:${worker.nam
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/71ae5f324e123a82.
Report an issue: GitHub.