temporalio/temporal · error

registrable component validation error: search attribute…

Error message

registrable component validation error: search attribute alias %q is already defined

What it means

This panic occurs when two SearchAttribute entries passed to WithSearchAttributes on the same RegistrableComponent use the same alias. The mapper stores aliasToField one-to-one, so a duplicate alias would silently overwrite the earlier mapping; registration instead panics to surface the conflict at startup.

Solutions

  1. Deduplicate the SearchAttribute list before passing it to WithSearchAttributes
  2. Rename one of the colliding aliases to a unique name
  3. Centralize the component's search attribute definitions in one place so duplicates are obvious

Example fix

// before
chasm.WithSearchAttributes(saStatus, saOrderStatus) // both alias "Status"
// after
chasm.WithSearchAttributes(saStatus) // single definition per alias
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, sa := range attrs {
    if seen[sa.definition().alias] {
        return fmt.Errorf("duplicate alias %q", sa.definition().alias)
    }
    seen[sa.definition().alias] = true
}

Prevention

When it happens

Trigger: Calling chasm.WithSearchAttributes(sa1, sa2, ...) where sa1.definition().alias == sa2.definition().alias, or calling WithSearchAttributes twice on the same component with a repeated alias (alias already present in aliasToField).

Common situations: Copy-pasting a SearchAttribute list where an attribute was declared twice; two team members adding attributes with the same short name (e.g. 'Status'); refactoring that merged two attribute lists without deduplicating.

Related errors


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

Appendix: source

Thrown at chasm/registrable_component.go:149

				continue
			}

			if sadefs.IsChasmSystem(alias) {
				//nolint:forbidigo
				panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is a CHASM system search attribute", alias))
			}
			if !sadefs.IsSystem(alias) && sadefs.IsReserved(alias) {
				//nolint:forbidigo
				panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is a reserved search attribute", alias))
			}

			if _, ok := rc.searchAttributesMapper.systemAliasToField[alias]; ok {
				//nolint:forbidigo
				panic(fmt.Sprintf("registrable component validation error: CHASM search attribute alias %q is already defined as a system search attribute alias", alias))
			}
			if _, ok := rc.searchAttributesMapper.aliasToField[alias]; ok {
				//nolint:forbidigo
				panic(fmt.Sprintf("registrable component validation error: search attribute alias %q is already defined", alias))
			}
			if _, ok := rc.searchAttributesMapper.fieldToAlias[field]; ok {
				//nolint:forbidigo
				panic(fmt.Sprintf("registrable component validation error: search attribute field %q is already defined", field))
			}

			rc.searchAttributesMapper.aliasToField[alias] = field
			rc.searchAttributesMapper.fieldToAlias[field] = alias
			rc.searchAttributesMapper.saTypeMap[field] = valueType
		}
	}
}

// WithContextValues allows specifying key-value pairs that will be available in the Context
// via the Value() method whenever the chasm framework starts, updates, reads, polls, executes or
// validates tasks on a component.
//
// This is useful for propagating values needed for those processing logic but are not avaiable via the

View on GitHub (pinned to bde624efd1)