temporalio/temporal · error

invalid number of custom search attributes for type %s (must

Error message

invalid number of custom search attributes for type %s (must be between 0 and 99)

What it means

Validation error when a PersistenceCustomSearchAttributes value (the configured limit of custom search attributes for that type) is negative or exceeds 99. Temporal caps custom search attributes per type at 99 to fit persistence limits.

Source

Thrown at temporal/fx.go:697

	clusterMetadataManager, err := factory.NewClusterMetadataManager()
	if err != nil {
		return svc.ClusterMetadata, svc.Persistence, fmt.Errorf("error initializing cluster metadata manager: %w", err)
	}
	defer clusterMetadataManager.Close()

	visCSAOverride := map[enumspb.IndexedValueType]int{}
	for tpName, value := range svc.Visibility.PersistenceCustomSearchAttributes {
		saType, ok := enumspb.IndexedValueType_shorthandValue[tpName]
		if !ok {
			return svc.ClusterMetadata,
				svc.Persistence,
				fmt.Errorf("invalid search attribute type: %s", tpName)
		}
		if value < 0 || value > 99 {
			return svc.ClusterMetadata,
				svc.Persistence,
				fmt.Errorf(
					"invalid number of custom search attributes for type %s (must be between 0 and 99)",
					tpName,
				)
		}
		visCSAOverride[enumspb.IndexedValueType(saType)] = value
	}

	visDataStores := []config.DataStore{
		svc.Persistence.GetVisibilityStoreConfig(),
		svc.Persistence.GetSecondaryVisibilityStoreConfig(),
	}
	indexSearchAttributes := make(map[string]*persistencespb.IndexSearchAttributes)
	for _, ds := range visDataStores {
		indexSearchAttributes[ds.GetIndexName()] = sadefs.GetDBIndexSearchAttributes(visCSAOverride)
	}

	clusterMetadata := svc.ClusterMetadata
	if len(clusterMetadata.ClusterInformation) > 1 {

View on GitHub (pinned to bde624efd1)

Solutions

  1. Set the value between 0 and 99 inclusive
  2. If more CSAs are needed, plan migration within the 99 limit
  3. Validate config before startup

Example fix

// before
visibility:
  persistenceCustomSearchAttributes:
    CustomIntField: 1000
// after
visibility:
  persistenceCustomSearchAttributes:
    CustomIntField: 50
Defensive patterns

Strategy: validation

Validate before calling

for name, n := range cfg.Visibility.PersistenceCustomSearchAttributes {
    if n < 0 || n > 99 {
        return fmt.Errorf("CSA limit for %s must be 0-99, got %d", name, n)
    }
}

Prevention

When it happens

Trigger: Setting a negative number or a number > 99 as the value for an entry in Visibility.PersistenceCustomSearchAttributes.

Common situations: Operator raising the CSA budget to e.g. 1000 not knowing the hard cap; copy-paste from docs with different limits; sign typo (-1) in YAML.

Related errors


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