{"record":{"id":"d571ee07e3a2f3cc","repo":"Tencent/WeKnora","slug":"invalid-task-id-format-s","errorCode":null,"errorMessage":"invalid task ID format: %s","messagePattern":"invalid task ID format: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/utils/taskid.go","lineNumber":73,"sourceCode":"\t}\n\n\tif len(businessID) > 0 && businessID[0] != \"\" {\n\t\tcomponents = append(components, sanitizeBusinessID(businessID[0]))\n\t}\n\n\treturn strings.Join(components, \"_\")\n}\n\n// ParseTaskID parses a task ID generated by GenerateTaskID and returns its components.\n// Returns taskType, tenantID, timestamp, uuid, businessID, and error.\n//\n// Task types may contain underscores (e.g. \"faq_import\", \"kb_clone\"), so the\n// parser locates the tenant/timestamp pair rather than assuming parts[0] is\n// the full task type.\nfunc ParseTaskID(taskID string) (taskType string, tenantID uint64, timestamp int64, uuidPart string, businessID string, err error) {\n\tparts := strings.Split(taskID, \"_\")\n\tif len(parts) < 4 {\n\t\terr = fmt.Errorf(\"invalid task ID format: %s\", taskID)\n\t\treturn\n\t}\n\n\ttenantIdx := -1\n\tfor i := 1; i < len(parts)-2; i++ {\n\t\tcandidateTenant, parseErr := strconv.ParseUint(parts[i], 10, 64)\n\t\tif parseErr != nil || candidateTenant == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tcandidateTS, parseErr := strconv.ParseInt(parts[i+1], 10, 64)\n\t\tif parseErr != nil || candidateTS < 1_000_000_000_000 {\n\t\t\tcontinue\n\t\t}\n\t\ttenantID = candidateTenant\n\t\ttimestamp = candidateTS\n\t\ttenantIdx = i\n\t\tbreak\n\t}","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/utils/taskid.go#L55-L91","documentation":"ParseTaskID splits a task ID on '_' and requires at least 4 segments: task type parts, tenant ID, timestamp, and UUID. If fewer than 4 underscore-separated parts exist the ID cannot contain the mandatory tenant_timestamp pair and 'invalid task ID format' is returned. Task types may themselves contain underscores, so the parser scans for the tenant/timestamp pair rather than trusting the first segment.","triggerScenarios":"ParseTaskID (via TaskTenantID or tests) receives a task ID with fewer than 4 '_'-separated segments — e.g. 'import_123', 'faqs', an empty string, or a truncated/corrupted ID read from a queue message or DB row.","commonSituations":"Legacy task IDs generated by an older ID format, IDs truncated by column limits or log copy-paste, hand-written test fixtures, or a producer bug that skipped appending tenant/timestamp/uuid segments.","solutions":["Regenerate the task ID with the correct format: <taskType>_<tenantID>_<timestamp>_<uuid> (e.g. faq_import_42_1700000000_ab12cd34)","Log the full raw taskID value and count its '_' segments to confirm the corruption point","Check the producer that created the ID for missing tenant/timestamp/uuid fields","Add validation at the producer side so malformed IDs are never enqueued"],"exampleFix":"// before\ntaskID := \"kb_clone_42\" // only 3 segments\n// after\ntaskID := \"kb_clone_42_1700000000_9f8e7d6c\" // taskType_tenant_ts_uuid","handlingStrategy":"validation","validationCode":"parts := strings.Split(taskID, \"_\")\nif len(parts) < 4 {\n    return fmt.Errorf(\"task ID %q too short: need <type>_<tenant>_<ts>_<uuid>\", taskID)\n}","typeGuard":"func looksLikeTaskID(id string) bool {\n    parts := strings.Split(id, \"_\")\n    if len(parts) < 4 { return false }\n    for i := 1; i < len(parts)-2; i++ {\n        tenant, e1 := strconv.ParseUint(parts[i], 10, 64)\n        _, e2 := strconv.ParseInt(parts[i+1], 10, 64)\n        if e1 == nil && e2 == nil && tenant > 0 { return true }\n    }\n    return false\n}","tryCatchPattern":"taskType, tenantID, ts, uuid, biz, err := utils.ParseTaskID(raw)\nif err != nil {\n    log.Printf(\"unparseable task ID %q: %v\", raw, err)\n    return fmt.Errorf(\"corrupt task ID from queue: %w\", err)\n}","preventionTips":["Never truncate task IDs (DB column limits, log copy-paste)","Generate IDs only through the producer helper that appends tenant/timestamp/uuid","Version task-ID formats if the legacy scheme lacked segments","Validate IDs at queue consumption before processing"],"tags":["task-id","parsing","validation"],"backgroundTag":"invalid-task-id-format","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}