{"record":{"id":"f32ed42fbea6d995","repo":"temporalio/temporal","slug":"task-s-is-already-registered","errorCode":null,"errorMessage":"task %s is already registered","messagePattern":"task (.+?) is already registered","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"chasm/registry.go","lineNumber":307,"sourceCode":"\t}\n\treturn r.validateVisibilityBusinessIDAlias(rc)\n}\n\nfunc (r *Registry) registerTask(\n\tlib namer,\n\trt *RegistrableTask,\n) error {\n\tif err := r.validateName(rt.taskType); err != nil {\n\t\treturn err\n\t}\n\n\tfqn, id, err := rt.registerToLibrary(lib)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif _, ok := r.rtByFqn[fqn]; ok {\n\t\treturn fmt.Errorf(\"task %s is already registered\", fqn)\n\t}\n\n\tif existingTask, ok := r.rtByID[id]; ok {\n\t\treturn fmt.Errorf(\"task type ID %d collision between %s and %s\", id, fqn, existingTask.fqType())\n\t}\n\n\tif !(rt.goType.Kind() == reflect.Struct ||\n\t\t(rt.goType.Kind() == reflect.Pointer && rt.goType.Elem().Kind() == reflect.Struct)) {\n\t\treturn fmt.Errorf(\"task type %s must be struct or pointer to struct\", rt.goType.String())\n\t}\n\tif _, ok := r.rtByGoType[rt.goType]; ok {\n\t\treturn fmt.Errorf(\"task type %s is already registered\", rt.goType.String())\n\t}\n\tif !(rt.componentGoType.Kind() == reflect.Interface ||\n\t\t(rt.componentGoType.Kind() == reflect.Struct ||\n\t\t\t(rt.componentGoType.Kind() == reflect.Pointer && rt.componentGoType.Elem().Kind() == reflect.Struct)) &&\n\t\t\trt.componentGoType.AssignableTo(reflect.TypeFor[Component]())) {\n\t\treturn fmt.Errorf(\"component type %s must be and interface or struct that implements Component interface\", rt.componentGoType.String())","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/chasm/registry.go#L289-L325","documentation":"registerTask found an existing RegistrableTask under the same fully-qualified name (library + task type) in r.rtByFqn. FQNs must be unique across the registry because they name the task in persisted data and lookups. This differs from the Go-type duplicate error — same name, different type still collides.","triggerScenarios":"Registering two tasks whose (library name, task type name) pairs resolve to the same FQN; registering the same task type under two different Go types; re-running registration with a renamed Go type but same name.","commonSituations":"Renaming a task struct without changing its registered name after a release; two teams independently picking the same task name in the same library; copying registration lines across services sharing a registry.","solutions":["Remove or deduplicate the second chasm.Register call for that task.","Give the second task a unique taskType name (e.g. prefix with the owning package).","If the FQN must stay stable for already-persisted data, keep one canonical registration and delete the new one."],"exampleFix":"// before\nchasm.RegisterTask[CleanupWorker, OrderImpl](reg, \"cleanup\", opts)\nchasm.RegisterTask[CleanupWorkerV2, OrderImpl](reg, \"cleanup\", opts)\n// after\nchasm.RegisterTask[CleanupWorker, OrderImpl](reg, \"cleanup\", opts)\nchasm.RegisterTask[CleanupWorkerV2, OrderImpl](reg, \"cleanup_v2\", opts)","handlingStrategy":"validation","validationCode":"fqn := libName + \".\" + taskTypeName\nif existingFQNs[fqn] {\n\treturn fmt.Errorf(\"task %s already registered\", fqn)\n}","typeGuard":null,"tryCatchPattern":"if err := chasm.RegisterTask[T, C](reg, name, opts); err != nil && strings.Contains(err.Error(), \"is already registered\") {\n\treturn nil // idempotent re-registration\n}","preventionTips":["Prefix task names with their owning package to keep FQNs unique.","Keep all task registrations in one central bootstrap function.","Never rename a registered task's name after deployment without a migration plan."],"tags":["chasm","registry","duplicate-registration","task-registration"],"backgroundTag":"duplicate-task-registration","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}