{"record":{"id":"39aff9ec7e6bf1b4","repo":"temporalio/temporal","slug":"unknown-field-type-v","errorCode":null,"errorMessage":"Unknown field type: %v","messagePattern":"Unknown field type: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/persistence/visibility/store/elasticsearch/visibility_store.go","lineNumber":1313,"sourceCode":"\t\treturn stringVal, nil\n\tcase enumspb.INDEXED_VALUE_TYPE_INT, enumspb.INDEXED_VALUE_TYPE_DOUBLE:\n\t\tnumberVal, isNumber := val.(json.Number)\n\t\tif !isNumber {\n\t\t\treturn nil, fmt.Errorf(\"%w: expected json.Number got %T\", errUnexpectedJSONFieldType, val)\n\t\t}\n\t\tif t == enumspb.INDEXED_VALUE_TYPE_INT {\n\t\t\treturn numberVal.Int64()\n\t\t}\n\t\treturn numberVal.Float64()\n\tcase enumspb.INDEXED_VALUE_TYPE_BOOL:\n\t\tboolVal, isBool := val.(bool)\n\t\tif !isBool {\n\t\t\treturn nil, fmt.Errorf(\"%w: expected bool got %T\", errUnexpectedJSONFieldType, val)\n\t\t}\n\t\treturn boolVal, nil\n\t}\n\n\tpanic(fmt.Sprintf(\"Unknown field type: %v\", t))\n}\n\nfunc ConvertElasticsearchClientError(message string, err error, logger log.Logger) error {\n\t// This message is returned to client, avoiding including too much details.\n\terrMessage := fmt.Sprintf(\"%s: %s\", message, shortErrorMessage(err))\n\tvar elasticErr *elastic.Error\n\tswitch {\n\tcase errors.As(err, &elasticErr):\n\t\t// Logging the full error message, useful for debugging.\n\t\tlogger.Error(message, tag.ESResponseStatus(elasticErr.Status), tag.Error(err))\n\t\tswitch elasticErr.Status {\n\t\tcase http.StatusBadRequest:\n\t\t\t// Returning InvalidArgument error will prevent retry on a caller side.\n\t\t\treturn serviceerror.NewInvalidArgument(errMessage)\n\t\tcase http.StatusTooManyRequests:\n\t\t\treturn &serviceerror.ResourceExhausted{\n\t\t\t\tCause:   enumspb.RESOURCE_EXHAUSTED_CAUSE_SYSTEM_OVERLOADED,\n\t\t\t\tScope:   enumspb.RESOURCE_EXHAUSTED_SCOPE_SYSTEM,","sourceCodeStart":1295,"sourceCodeEnd":1331,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/visibility/store/elasticsearch/visibility_store.go#L1295-L1331","documentation":"During JSON document conversion for Elasticsearch indexing, a type switch over protobuf field value types falls through to a final panic 'Unknown field type: %v' when it encounters a *persistencespb (proto) type it does not explicitly handle. This means the visibility encoder was asked to index a field whose Go/proto type has no mapping to an Elasticsearch field type — almost always after a new field or message type was added without updating the ES visibility encoder.","triggerScenarios":"Writing workflow visibility data containing a newly introduced proto field type to the Elasticsearch visibility store; the converter's switch on t (field value type) reaches the default panic branch at visibility_store.go:1313.","commonSituations":"Server upgrade where new persisted proto fields (e.g. new enum/message in persistencespb) are indexed by an ES visibility store but the field-type mapping switch was not extended; running an older ES visibility encoder against state written by a newer server (version skew); custom field additions in forks.","solutions":["Extend the type switch in the ES visibility conversion function to map the missing proto type to its Elasticsearch field representation.","Upgrade the server/encoder to a version that supports the new field types (fix version skew between frontend/history and the visibility store).","Identify the offending field from the panic's %v output and either add a converter case or exclude the field from visibility indexing.","Temporarily disable/roll back the ES visibility write path until the encoder supports the new types."],"exampleFix":"// before\nswitch t := val.(type) {\ncase string: ...\ncase bool: ...\n}\npanic(fmt.Sprintf(\"Unknown field type: %v\", t))\n// after\nswitch t := val.(type) {\ncase string: ...\ncase bool: ...\ncase *persistencespb.NewFieldType: ...\ndefault:\n    return nil, fmt.Errorf(\"%w: unknown field type %T\", errUnexpectedJSONFieldType, val)\n}","handlingStrategy":"validation","validationCode":"func fieldSupported(v interface{}) bool {\n    switch v.(type) {\n    case string, int64, bool, float64:\n        return true\n    default:\n        logger.Warn(\"unsupported visibility field type\", tag.Type(fmt.Sprintf(\"%T\", v)))\n        return false\n    }\n}","typeGuard":"func isKnownFieldType(t interface{}) bool { switch t.(type) { case string, int64, bool, float64: return true; default: return false } }","tryCatchPattern":"// replace the panic default with an error return so the caller can skip/drop the field\nunknown, ok := val.(*persistencespb.UnsupportedType)\nif !ok { return nil, fmt.Errorf(\"%w: unknown field type %T\", errUnexpectedJSONFieldType, val) }","preventionTips":["Extend the ES field-type converter whenever new persistencespb field types are added","Pin server and visibility encoder versions together to avoid skew","Add CI tests converting a full mutable-state document to ES JSON after proto changes"],"tags":["elasticsearch","panic","visibility","encoding","proto"],"backgroundTag":"unknown-proto-field-type","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}