From 425e7deea9534e28debc8a0ce46070cfdccc7de7 Mon Sep 17 00:00:00 2001 From: sijie-ni-0214 Date: Thu, 18 Jun 2026 02:24:27 +0800 Subject: [PATCH] fix: Reject dropping active TTL field (#50479) issue: https://github.com/milvus-io/milvus/issues/50476 This PR rejects dropping a field when it is referenced by the collection `ttl_field` property. Users need to drop the property first, which avoids leaving dangling entity-level TTL metadata after Drop Field. Validation: - gofumpt -l internal/proxy/task.go internal/proxy/task_test.go - git diff --check - TestValidateDropField Signed-off-by: sijie-ni-0214 --- internal/proxy/task.go | 6 ++++++ internal/proxy/task_test.go | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/internal/proxy/task.go b/internal/proxy/task.go index 65c3147fa6..5afccd9b3c 100644 --- a/internal/proxy/task.go +++ b/internal/proxy/task.go @@ -1219,6 +1219,12 @@ func validateDropField(schema *schemapb.CollectionSchema, fieldName string) erro return merr.WrapErrParameterInvalidMsg("field not found: %s", fieldName) } + for _, property := range schema.GetProperties() { + if property.GetKey() == common.CollectionTTLFieldKey && property.GetValue() == fieldName { + return merr.WrapErrParameterInvalidMsg("cannot drop field %s because it is referenced by collection property %s, drop the property first", fieldName, common.CollectionTTLFieldKey) + } + } + // Check: cannot drop system fields if funcutil.SliceContain([]string{common.RowIDFieldName, common.TimeStampFieldName, common.MetaFieldName, common.NamespaceFieldName}, fieldName) { return merr.WrapErrParameterInvalidMsg("cannot drop system field: %s", fieldName) diff --git a/internal/proxy/task_test.go b/internal/proxy/task_test.go index c69d7b9f05..3d3e81e8f9 100644 --- a/internal/proxy/task_test.go +++ b/internal/proxy/task_test.go @@ -8266,6 +8266,24 @@ func TestValidateDropField(t *testing.T) { assert.Contains(t, err.Error(), "cannot drop dynamic field") }) + t.Run("cannot drop active ttl field", func(t *testing.T) { + schema := &schemapb.CollectionSchema{ + Name: "test_collection", + Fields: []*schemapb.FieldSchema{ + {FieldID: 100, Name: "id", DataType: schemapb.DataType_Int64, IsPrimaryKey: true}, + {FieldID: 101, Name: "vector", DataType: schemapb.DataType_FloatVector, TypeParams: []*commonpb.KeyValuePair{{Key: "dim", Value: "128"}}}, + {FieldID: 102, Name: "ttl", DataType: schemapb.DataType_Timestamptz, Nullable: true}, + }, + Properties: []*commonpb.KeyValuePair{ + {Key: common.CollectionTTLFieldKey, Value: "ttl"}, + }, + } + + err := validateDropField(schema, "ttl") + assert.Error(t, err) + assert.Contains(t, err.Error(), "referenced by collection property ttl_field") + }) + t.Run("field referenced by function - input", func(t *testing.T) { err := validateDropField(baseSchema, "scalar_field") assert.Error(t, err)