{"record":{"id":"e9013007111cc251","repo":"temporalio/temporal","slug":"w-t-expected-string","errorCode":null,"errorMessage":"%w: %T (expected string)","messagePattern":"%w: %T \\(expected string\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/persistence/sql/sqlplugin/mysql/visibility.go","lineNumber":340,"sourceCode":"\t}\n\trow.StartTime = mdb.converter.FromMySQLDateTime(row.StartTime)\n\trow.ExecutionTime = mdb.converter.FromMySQLDateTime(row.ExecutionTime)\n\tif row.CloseTime != nil {\n\t\tcloseTime := mdb.converter.FromMySQLDateTime(*row.CloseTime)\n\t\trow.CloseTime = &closeTime\n\t}\n\tif row.SearchAttributes != nil {\n\t\tfor saName, saValue := range *row.SearchAttributes {\n\t\t\tswitch typedSaValue := saValue.(type) {\n\t\t\tcase []any:\n\t\t\t\t// the only valid type is slice of strings\n\t\t\t\tstrSlice := make([]string, len(typedSaValue))\n\t\t\t\tfor i, item := range typedSaValue {\n\t\t\t\t\tswitch v := item.(type) {\n\t\t\t\t\tcase string:\n\t\t\t\t\t\tstrSlice[i] = v\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn fmt.Errorf(\"%w: %T (expected string)\", sqlplugin.ErrInvalidKeywordListDataType, v)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t(*row.SearchAttributes)[saName] = strSlice\n\t\t\tdefault:\n\t\t\t\t// no-op\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":322,"sourceCodeEnd":351,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/sql/sqlplugin/mysql/visibility.go#L322-L351","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Identify the offending attribute name and row (from the %T type in the message) and inspect its JSON in the visibility table.","Fix or delete the malformed row's search attributes data.","Validate search attribute values are strings before writing keyword-list attributes.","Upgrade/patch the writer that allowed non-string values into keyword-list fields."],"exampleFix":"// before: writing unvalidated values\nsa[\"KeywordListField\"] = []interface{}{123}\n// after: enforce strings\nif _, ok := v.(string); !ok { return fmt.Errorf(\"keyword list value must be string\") }","handlingStrategy":"type-guard","validationCode":"// Go: validate keyword list values before writing\nfor _, v := range values {\n    if _, ok := v.(string); !ok {\n        return fmt.Errorf(\"keyword list values must be strings, got %T\", v)\n    }\n}","typeGuard":"func isStringSlice(items []interface{}) ([]string, bool) {\n    out := make([]string, len(items))\n    for i, v := range items {\n        s, ok := v.(string)\n        if !ok { return nil, false }\n        out[i] = s\n    }\n    return out, true\n}","tryCatchPattern":"// Go\nrow, err := store.SelectFromVisibility(ctx, req)\nif err != nil && errors.Is(err, sqlplugin.ErrInvalidKeywordListDataType) {\n    // data corruption path: skip/quarantine the row, alert\n    return nil, fmt.Errorf(\"corrupt keyword-list data: %w\", err)\n}","preventionTips":["Validate custom search attribute types at ingestion time","Never hand-edit search attributes JSON in the DB","Monitor ErrInvalidKeywordListDataType occurrences as data-corruption signals","Pin writer versions so serialization bugs are caught in tests"],"tags":["mysql","search-attributes","data-corruption","type-mismatch","keyword-list"],"backgroundTag":"invalid-keyword-list-data-type","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}