temporalio/temporal · error

nexus service %s is already registered

Error message

nexus service %s is already registered

What it means

registerNexusService rejects registering a nexus.Service whose Name already exists in r.nexusServices. Nexus service names must be unique in the registry because they route inbound Nexus calls to handlers.

Source

Thrown at chasm/registry.go:370

	return nil
}

func (r *Registry) warnUnmanagedFields(fqn string, rc *RegistrableComponent) {
	var unmanagedFields []string
	for f := range unmanagedFieldsOf(rc.goType) {
		unmanagedFields = append(unmanagedFields, fmt.Sprintf("%s %s", f.name, f.typ))
	}
	if len(unmanagedFields) > 0 {
		r.logger.Info(fmt.Sprintf(
			"Warning: CHASM component %s declares state fields that won't be managed by CHASM:\n\t%s",
			fqn,
			strings.Join(unmanagedFields, "\n\t")))
	}
}

func (r *Registry) registerNexusService(svc *nexus.Service) error {
	if _, ok := r.nexusServices[svc.Name]; ok {
		return fmt.Errorf("nexus service %s is already registered", svc.Name)
	}
	r.nexusServices[svc.Name] = svc
	return nil
}

// NexusServices returns all registered Nexus services.
func (r *Registry) NexusServices() map[string]*nexus.Service {
	// Return a copy to prevent external modification
	services := make(map[string]*nexus.Service, len(r.nexusServices))
	maps.Copy(services, r.nexusServices)
	return services
}

func (r *Registry) componentContextValue(key any) any {
	if v, ok := r.rcContextValues[key]; ok {
		return v.v
	}
	return nil

View on GitHub (pinned to bde624efd1)

Solutions

  1. Remove the duplicate registration so each nexus service name is registered once.
  2. Give the second service a unique name.
  3. If both packages need the same service, export one registration and import it instead of duplicating.

Example fix

// before
reg.RegisterNexusService(nexus.NewService("billing", ...))
reg.RegisterNexusService(nexus.NewService("billing", ...))
// after
reg.RegisterNexusService(nexus.NewService("billing", ...))
Defensive patterns

Strategy: validation

Validate before calling

if registeredNexusNames[svc.Name] {
	return fmt.Errorf("nexus service %s already registered", svc.Name)
}

Try / catch

if err := registerNexusService(reg, svc); err != nil && strings.Contains(err.Error(), "is already registered") {
	return nil // idempotent bootstrap
}

Prevention

When it happens

Trigger: Registering the same nexus service name twice via chasm.Register; two packages' init() both registering a service with the same name; registering two distinct nexus.Service instances that share a name.

Common situations: Shared infrastructure package and app bootstrap both registering the same service name; renaming a service but leaving the old registration in place; multi-tenant setups reusing a name across libraries loaded into one binary.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/57baceb17bc4a7f5. Report an issue: GitHub.