temporalio/temporal · error

name %s is invalid. name must follow golang identifier rules

Error message

name %s is invalid. name must follow golang identifier rules: %s

What it means

validateName rejects a component or task name that is empty or does not match nameValidator, a regex enforcing Go identifier rules (as reported via nameValidator.String()). Names become parts of FQNs and persisted identifiers, so they must be valid identifiers.

Source

Thrown at chasm/registry.go:339

	if !(rt.componentGoType.Kind() == reflect.Interface ||
		(rt.componentGoType.Kind() == reflect.Struct ||
			(rt.componentGoType.Kind() == reflect.Pointer && rt.componentGoType.Elem().Kind() == reflect.Struct)) &&
			rt.componentGoType.AssignableTo(reflect.TypeFor[Component]())) {
		return fmt.Errorf("component type %s must be and interface or struct that implements Component interface", rt.componentGoType.String())
	}

	r.rtByFqn[fqn] = rt
	r.rtByID[id] = rt
	r.rtByGoType[rt.goType] = rt
	return nil
}

func (r *Registry) validateName(n string) error {
	if n == "" {
		return errors.New("name must not be empty")
	}
	if !nameValidator.MatchString(n) {
		return fmt.Errorf("name %s is invalid. name must follow golang identifier rules: %s", n, nameValidator.String())
	}
	return nil
}

func (r *Registry) validateVisibilityBusinessIDAlias(rc *RegistrableComponent) error {
	if !hasVisibilityField(rc.goType) {
		return nil
	}
	// Archetypes that contain a Field[*Visibility] must specify WithBusinessIDAlias.
	if !rc.hasBusinessIDAlias() {
		return fmt.Errorf("component %s has Field[*Visibility] but no businessID alias; use WithBusinessIDAlias option", rc.componentType)
	}
	return nil
}

func (r *Registry) warnUnmanagedFields(fqn string, rc *RegistrableComponent) {
	var unmanagedFields []string
	for f := range unmanagedFieldsOf(rc.goType) {

View on GitHub (pinned to bde624efd1)

Solutions

  1. Rename to a valid Go identifier: letters/digits/underscores, not starting with a digit, e.g. "order_cleanup".
  2. Check the regex in the error message to see exactly which characters are allowed.
  3. If the name comes from config, sanitize/validate it before calling Register.

Example fix

// before
chasm.RegisterTask[T, C](reg, "order-cleanup", opts)
// after
chasm.RegisterTask[T, C](reg, "order_cleanup", opts)
Defensive patterns

Strategy: validation

Validate before calling

var nameValidator = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
if !nameValidator.MatchString(name) {
	return fmt.Errorf("name %q must be a valid Go identifier", name)
}

Prevention

When it happens

Trigger: Registering a component/task whose registered name contains hyphens, spaces, dots, leading digits, or other non-identifier characters; passing an empty name string.

Common situations: Using a kebab-case or dotted service name like "order-cleanup" or "orders.v1" as the task type; building names dynamically from config or env values with unexpected formatting; forgetting the name argument entirely (empty string).

Related errors


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