temporalio/temporal · error

%w: %T (expected string)

Error message

%w: %T (expected string)

What it means

Returned by processRowFromDB (MySQL visibility store) when a keyword-list search attribute value read from the DB contains an element that is not a Go string. It wraps sqlplugin.ErrInvalidKeywordListDataType and includes the actual Go type found (%T). This indicates corrupted or unexpectedly encoded data in the search attributes JSON column.

Source

Thrown at common/persistence/sql/sqlplugin/mysql/visibility.go:340

	}
	row.StartTime = mdb.converter.FromMySQLDateTime(row.StartTime)
	row.ExecutionTime = mdb.converter.FromMySQLDateTime(row.ExecutionTime)
	if row.CloseTime != nil {
		closeTime := mdb.converter.FromMySQLDateTime(*row.CloseTime)
		row.CloseTime = &closeTime
	}
	if row.SearchAttributes != nil {
		for saName, saValue := range *row.SearchAttributes {
			switch typedSaValue := saValue.(type) {
			case []any:
				// the only valid type is slice of strings
				strSlice := make([]string, len(typedSaValue))
				for i, item := range typedSaValue {
					switch v := item.(type) {
					case string:
						strSlice[i] = v
					default:
						return fmt.Errorf("%w: %T (expected string)", sqlplugin.ErrInvalidKeywordListDataType, v)
					}
				}
				(*row.SearchAttributes)[saName] = strSlice
			default:
				// no-op
			}
		}
	}
	return nil
}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Identify the offending attribute name and row (from the %T type in the message) and inspect its JSON in the visibility table.
  2. Fix or delete the malformed row's search attributes data.
  3. Validate search attribute values are strings before writing keyword-list attributes.
  4. Upgrade/patch the writer that allowed non-string values into keyword-list fields.

Example fix

// before: writing unvalidated values
sa["KeywordListField"] = []interface{}{123}
// after: enforce strings
if _, ok := v.(string); !ok { return fmt.Errorf("keyword list value must be string") }
Defensive patterns

Strategy: type-guard

Validate before calling

// Go: validate keyword list values before writing
for _, v := range values {
    if _, ok := v.(string); !ok {
        return fmt.Errorf("keyword list values must be strings, got %T", v)
    }
}

Type guard

func isStringSlice(items []interface{}) ([]string, bool) {
    out := make([]string, len(items))
    for i, v := range items {
        s, ok := v.(string)
        if !ok { return nil, false }
        out[i] = s
    }
    return out, true
}

Try / catch

// Go
row, err := store.SelectFromVisibility(ctx, req)
if err != nil && errors.Is(err, sqlplugin.ErrInvalidKeywordListDataType) {
    // data corruption path: skip/quarantine the row, alert
    return nil, fmt.Errorf("corrupt keyword-list data: %w", err)
}

Prevention

When it happens

Trigger: SelectFromVisibility or GetFromVisibility decoding a row whose keyword-list SearchAttributes JSON contains a non-string element — e.g. a numeric or boolean value stored under a keyword-list key, typically from a writer bug, manual row edits, or a driver returning []interface{} of non-strings.

Common situations: Corrupted rows after manual DB manipulation; data written by an older/buggy version; misuse of a keyword-list field with non-string values via custom search attribute ingestion.

Related errors


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