{"record":{"id":"d7d3a6e9ef61fd15","repo":"Yeachan-Heo/oh-my-codex","slug":"invalid-task-id-rawtaskid-must-be-a-positiv","errorCode":null,"errorMessage":"Invalid task_id: \"${rawTaskId}\". Must be a positive integer (digits only, max 20 digits).","messagePattern":"Invalid task_id: \"(.+?)\"\\. Must be a positive integer \\(digits only, max 20 digits\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/team/api-interop.ts","lineNumber":581,"sourceCode":"  return `Use CLI interop: omx team api ${operation} --input '${payload}' --json`;\n}\n\nfunction validateCommonFields(args: Record<string, unknown>, options: { skipTeamName?: boolean } = {}): void {\n  const teamName = String(args.team_name || '').trim();\n  if (!options.skipTeamName && teamName && !TEAM_NAME_SAFE_PATTERN.test(teamName)) {\n    throw new Error(`Invalid team_name: \"${teamName}\". Must match /^[a-z0-9][a-z0-9-]{0,29}$/ (lowercase alphanumeric + hyphens, max 30 chars).`);\n  }\n\n  for (const workerField of ['worker', 'from_worker', 'to_worker']) {\n    const workerVal = String(args[workerField] || '').trim();\n    if (workerVal && !WORKER_NAME_SAFE_PATTERN.test(workerVal)) {\n      throw new Error(`Invalid ${workerField}: \"${workerVal}\". Must match /^[a-z0-9][a-z0-9-]{0,63}$/ (lowercase alphanumeric + hyphens, max 64 chars).`);\n    }\n  }\n\n  const rawTaskId = String(args.task_id || '').trim();\n  if (rawTaskId && !TASK_ID_SAFE_PATTERN.test(rawTaskId)) {\n    throw new Error(`Invalid task_id: \"${rawTaskId}\". Must be a positive integer (digits only, max 20 digits).`);\n  }\n}\n\n\nfunction normalizeTeamDisplayLookupName(value: string): string {\n  return value\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, '-')\n    .replace(/-+/g, '-')\n    .replace(/^-|-$/g, '')\n    .slice(0, 30)\n    .replace(/-$/, '');\n}\n\nfunction assertUnsafeTeamNameMatchesKnownDisplay(rawTeamName: string, cwd: string): void {\n  if (TEAM_NAME_SAFE_PATTERN.test(rawTeamName)) return;\n  const normalized = normalizeTeamDisplayLookupName(rawTeamName);\n  const matchesKnownDisplay = listTeamLookupCandidates(cwd).some((candidate) => {","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/team/api-interop.ts#L563-L599","documentation":"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.","triggerScenarios":"Passing task_id such as '12a', 'task-12', '-5', '1e3', or a 25-digit string in the args object.","commonSituations":"Forwarding IDs from URLs or tickets with prefixes; scientific notation from a JSON serializer; extremely long numeric IDs from external systems.","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"],"exampleFix":"// before\napi('get-task', { task_id: 'task-12' });\n// after\napi('get-task', { task_id: '12' });","handlingStrategy":"validation","validationCode":"const TASK_ID = /^\\d{1,20}$/;\nconst id = String(args.task_id || '').trim();\nif (id && !TASK_ID.test(id)) throw new RangeError('task_id must be digits (max 20)');","typeGuard":"const isSafeTaskId = (id: string): boolean => /^\\d{1,20}$/.test(id);","tryCatchPattern":null,"preventionTips":["Strip prefixes like 'TASK-' at ingestion boundaries","Never pass floats or exponent notation as task IDs"],"tags":["validation","task-id","team-api"],"backgroundTag":"invalid-identifier-format","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}