Skip to content

fix: five fixes from the python-parity audit (two source-breaking) - #368

Open
g-despot wants to merge 15 commits into
mainfrom
fix/client-parity-batch
Open

fix: five fixes from the python-parity audit (two source-breaking)#368
g-despot wants to merge 15 commits into
mainfrom
fix/client-parity-batch

Conversation

@g-despot

@g-despot g-despot commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Five fixes from the python-parity audit, one commit each.

  • 55b0693Multi2VecGoogleGemini emitted multi2vec-google-gemini, which no server has, so it could never create a collection. Now emits multi2vec-google with the Gemini endpoint (server ≥ 1.34.20). Dropping required from ProjectId/Location also fixes a cross-client break: a collection created by python's multi2vec_google_gemini could not be read at all.
  • 0e83cd9 — send incremental_base_backup_id on backup create. The DTO carried it; nothing set it.
  • 6c64793 — backup list discarded Size and the base id it had already parsed, so Size was null for every listed backup.
  • 4ef693c — add generative-deepseek (server ≥ 1.36.19), collection config and runtime provider, with the vendored proto update it needs.
  • 4356731 — aggregate reported 0/0.0/false where the server sent nothing. Text, Int, Number, Boolean and Date are now presence-checked, Count included.

Breaking

Multi2VecGoogleGemini is now an [Obsolete] shim over Multi2VecGoogle. This breaks at runtime, not only at compile time: the factory returns a Multi2VecGoogle, so is/as/switch arms on the old type silently stop matching, and a switch handling both no longer compiles (CS8120).

  • Multi2VecGoogleGemini.Model removed — use .ModelId.
  • Multi2VecGoogle.ProjectId/Location no longer required; getters string!string?.
  • Aggregate.Boolean.PercentageTrue/PercentageFalse/TotalTrue/TotalFalse are nullable.
  • BackupCreateRequest primary constructor and Deconstruct go 6 → 7 parameters.

All of these are also binary-breaking: recompile, or MissingMethodException. Migration notes are in the changelog.

Notes

  • Incremental backups have two different server floors: create accepts the field from 1.34.18, but read only returns it from 1.37.6 — below that, a null base id does not mean the backup is non-incremental. The client gates create at 1.37.0, the documented feature floor, as python does.
  • The deepseek integration test uses integral floats deliberately. The server drops fractional floats for this module on named-vector classes — class_settings_property_helper.go falls through to defaultValue for any non-integer json.Number, and deepseek passes -100.0 as that default, which then trips its own validation. generative-openai behaves the same way. The client payload is correct; fractional values are covered by unit tests.
  • Two commit messages carry incorrect python-parity claims, corrected here rather than by rewriting history: 6c64793 says python has this field on BackupListReturn (it has no such field), and 0e83cd9 says python does not lowercase the id (it lowercases both).
  • Not addressed here: the client still cannot read a config named multi2vec-google, because Multi2VecGoogle registers only the legacy multi2vec-palm and the registry has no alt-identifier support. Needs a registry change; tracked separately.

Closes #352

Multi2VecGoogleGemini declared [Vectorizer("multi2vec-google-gemini")]. No
such module exists: modules/multi2vec-google/module.go names the module
"multi2vec-google" with the single alias "multi2vec-palm", and grepping the
server for "multi2vec-google-gemini" returns nothing. A live 1.39.0 rejects
it outright:

  422 {"error":[{"message":"target vector \"default\": vectorizer: no
  module with name \"multi2vec-google-gemini\" present"}]}

So the factory could not create a collection at all.

Gemini is reached through the one Google multimodal module by pointing
apiEndpoint at generativelanguage.googleapis.com — what python does with a
single _Multi2VecGoogleConfig and a switched endpoint, and what this client
already does on the text side in Text2VecGoogleGemini. Multi2VecGoogle grows
that ApiEndpoint property and VectorizerFactory.Multi2VecGoogleGemini stays
as the ergonomic entry point, now returning a Multi2VecGoogle.

ProjectId and Location drop `required` and become nullable, matching
python's Optional[str]. The Gemini API is scoped to neither, so both are
null and the REST serializer omits them. This also unbreaks readback: a
required member absent from the server's JSON makes System.Text.Json throw,
so a Gemini config could not have round-tripped even once creation worked.

Folds in the related gap: the Gemini path had neither Dimensions nor
VectorizeCollectionName, both of which Multi2VecGoogle has and python passes.
The Vertex overloads gain an apiEndpoint parameter, which the repo's own
WEAVIATE002 analyzer requires once the property exists, and which mirrors
Text2VecGoogle.

Source-breaking for anyone binding the record type, so Multi2VecGoogleGemini
survives as an [Obsolete] shim over Multi2VecGoogle following the
Multi2VecPalm/Text2VecPalm precedent. It deliberately carries no [Vectorizer]
attribute: VectorizerRegistry keys types by identifier and last write wins,
so a second type claiming "multi2vec-palm" would make deserialization of
every Google multimodal config depend on reflection order.

Tests: the two existing Gemini unit cases now pin the module name, the
endpoint and the absent Vertex fields; the string-array case carries the new
dimensions/vectorizeCollectionName and the weighted case stays without them
so omit-when-unset stays covered. New integration coverage creates both a
Gemini and a Vertex collection against a real server and asserts the round
trip; a RequireModule gate skips when the module is absent, and CI now
enables multi2vec-google so it runs there.
The generated DTO has carried Incremental_base_backup_id since the 1.37 spec
(Rest/Dto/Models.g.cs) and the server reads it
(entities/models/backup_create_request.go:51), but nothing in the client
could set it: BackupCreateRequest had no such member and
BuildBackupCreateRequest never populated one. Asking for an incremental
backup was impossible; python has had it since 4.20.2
(weaviate/backup/executor.py).

The version gate is on the field rather than on the operation. A
[RequiresWeaviateVersion] attribute on Create would refuse every backup on a
pre-1.37 server, which is a regression for plain backups, so this follows
CollectionsClient.EnsureTextAnalyzerFeaturesSupported instead: check only
when the caller actually supplied a base id, and throw the same
WeaviateVersionMismatchException the rest of the client's gates throw. Python
gates identically (executor.py:92-96).

The base id is passed through verbatim rather than lowercased. Python lowers
it, but this client does not lower request.Id either, and applying the rule
to one id and not the other would be the surprising behaviour.

Tests cover all four quadrants: the key reaches the wire when set, is absent
when unset, a pre-1.37 server rejects an incremental request with the right
RequiredVersion/ActualVersion, and a plain backup on that same old server
still succeeds.
ToModelListItem read the list payload and then threw two fields away.

Size is the outright bug: the property exists on Backup, the create-status
path fills it, and Anonymous3 carries it — but the list mapper never
assigned it, so every listed backup reported Size == null whatever the
server said.

The incremental base id had nowhere to go, so Backup gains it. Python added
the same field to BackupListReturn in 4.23.0. Anonymous3 is an nswag
anonymous-schema name, so it was re-checked rather than assumed: Rest/Backup.cs
decodes the list response as List<Dto.Anonymous3>, and that record's shape
(id/classes/status/startedAt/completedAt/size/incremental_base_backup_id)
matches the list item in the spec.

The create-status response carries incremental_base_backup_id too, and the
Backup model is shared between both paths, so that mapper sets it as well —
otherwise the field would have been silently null on the status path, which
is the same defect this commit removes from the list path.
The client had zero references to generative-deepseek. Adds the collection
config (GenerativeConfig.Deepseek + GenerativeConfigFactory.Deepseek +
the serialization arm) and the runtime provider (Providers.Deepseek +
GenerativeProviderFactory.Deepseek + the Search.Builders mapping), following
the Databricks precedent throughout.

Wire keys are taken from the server, not from the C# property names:
modules/generative-deepseek/config/class_settings.go spells the base url
"baseURL", and the camelCase policy happens to produce exactly that, so no
[JsonPropertyName] is needed. That is load-bearing rather than lucky — a
baseUrl/baseURL slip is silent, since the server ignores an unknown key and
quietly uses its own endpoint — so the unit test pins the literal string, and
was confirmed to fail when the casing is forced the other way.

Includes a vendored proto sync. src/Weaviate.Client/gRPC/proto/v1/
generative.proto was one feature behind upstream: GenerativeDeepseek was
missing from the GenerativeProvider oneof (field 16) along with the message
itself and GenerativeDeepseekMetadata, so the runtime provider could not be
expressed at all. The four hunks are copied verbatim from Weaviate v1.39.0's
grpc/proto/v1/generative.proto; the vendored file now differs from upstream
only by the deliberate `option csharp_namespace` line, and no other drift was
found in it. The metadata message is unused today — the client does not read
GenerativeMetadata anywhere — but is included so the file stays a faithful
copy and the next sync is a clean diff.

Note for the integration test: on a class using named vectors, Weaviate
1.39.0 rejects any fractional float in this module's config, e.g.
temperature 0.7 comes back as "Wrong temperature configuration, values are
between 0.0 and 2.0". The client sends ordinary JSON numbers and the same
body is accepted when the class uses a class-level vectorizer, so this is a
server defect: the value arrives as a json.Number, getNumberValue's
non-integer path returns the caller's defaultValue, and this module passes a
-100 sentinel there. generative-openai fails the same way; generative-cohere
does not. The integration test therefore uses integral floats so it exercises
all eight keys against a real server, and the unit test carries the
fractional values.
Every scalar in the aggregate reply is `optional` in aggregate.proto.
FromGrpcProperty read the Int, Number and Boolean ones unconditionally, so an
unset field surfaced as the field type's zero — indistinguishable from a real
aggregate of zeros. The Date branch six lines below already gated on its Has*
flags; Int, Number and Boolean were simply missed. Python fixed the same
defect in 4.21.2 (base_executor.py, python #2036).

Proven against a live 1.39.0 before the change: an OverAll with a filter
matching no objects and Metric.Integer(maximum, mean, sum) returned
Maximum == 0, and the new integration test failed with
"Assert.Null() Failure: Value of type 'Nullable<long>' has a value /
Expected: null / Actual: 0". Both aggregate shapes route through this one
method, so AggregateResult and AggregateGroupByResult are fixed together.

Boolean's four members were non-nullable and had to change type, which is
source-breaking; PublicAPI carries the *REMOVED*/re-add pairs. That half
cannot be shown against a live server, because 1.39.0 always populates all
four however few objects match and whatever metrics were requested — on an
empty match it sends totals of 0 and percentages of NaN. It is still wrong to
invent false/0 for a field the server did not send, so the guarantee is
pinned by a unit test that drives FromGrpcProperty off a proto message
directly, with a companion case proving a deliberate zero still survives as
zero rather than being swallowed.

Count stays unconditional, as in python: 0 is the right answer for an empty
aggregate, not a missing one.

The integration tests record two observed server behaviours worth knowing:
unrequested Int/Number sub-metrics really are absent (so the fix is what
makes them null), while the boolean members are always present.

@orca-security-eu orca-security-eu Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orca Security Scan Summary

Status Check Issues by priority
Passed Passed Infrastructure as Code high 0   medium 0   low 0   info 0 View in Orca
Passed Passed SAST high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Secrets high 0   medium 0   low 0   info 0 View in Orca
Passed Passed Vulnerabilities high 0   medium 0   low 0   info 0 View in Orca

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

Summary - Weaviate C# Client Coverage

Summary
Generated on: 08/19/2026 - 11:46:01
Coverage date: 08/19/2026 - 11:37:08 - 08/19/2026 - 11:44:58
Parser: MultiReport (133x Cobertura)
Assemblies: 3
Classes: 377
Files: 242
Line coverage: 47.8% (11406 of 23846)
Covered lines: 11406
Uncovered lines: 12440
Coverable lines: 23846
Total lines: 61249
Branch coverage: 36.8% (2539 of 6885)
Covered branches: 2539
Total branches: 6885
Method coverage: Feature is only available for sponsors

Coverage

Weaviate.Client - 49.7%
Name Line Branch
Weaviate.Client 49.7% 39.3%
Weaviate.Client.AggregateClient 19.5% 11.3%
Weaviate.Client.AggregateClientHybridExtensions 0%
Weaviate.Client.AliasClient 100% 62.5%
Weaviate.Client.ApiKeyTokenService 87.5% 50%
Weaviate.Client.Auth 38%
Weaviate.Client.AuthenticatedHttpHandler 75% 71.4%
Weaviate.Client.BackupClient 79.2% 44.1%
Weaviate.Client.BaseCollectionClient 0% 0%
Weaviate.Client.Batch.BatchContext 58% 50%
Weaviate.Client.Batch.BatchManager 39.2% 25.7%
Weaviate.Client.Batch.BatchOptions 25% 50%
Weaviate.Client.Batch.BatchResult 100%
Weaviate.Client.Batch.TaskHandle 83.3% 50%
Weaviate.Client.Cache.SchemaCache 69.4% 60%
Weaviate.Client.ClientConfiguration 100% 100%
Weaviate.Client.ClientConfigurationExtensions 35.2% 16.6%
Weaviate.Client.ClusterClient 86.2% 64.2%
Weaviate.Client.CollectionClient 98.7% 87.5%
Weaviate.Client.CollectionClientExtensions 100% 100%
Weaviate.Client.CollectionConfigClient 95.7% 68.7%
Weaviate.Client.CollectionsClient 47.7% 68.3%
Weaviate.Client.CollectionTokenizeClient 100% 50%
Weaviate.Client.Configure 48.6% 50%
Weaviate.Client.Connect 25.5% 0%
Weaviate.Client.DataClient 91.5% 78.7%
Weaviate.Client.DefaultTokenServiceFactory 27.6% 25%
Weaviate.Client.DependencyInjection.ScopedTokenServiceAdapter 0%
Weaviate.Client.DependencyInjection.WeaviateClientFactory 0% 0%
Weaviate.Client.DependencyInjection.WeaviateInitializationService 0%
Weaviate.Client.DependencyInjection.WeaviateOptions 50.9% 87.5%
Weaviate.Client.DependencyInjection.WeaviateServiceCollectionExtensions 0% 0%
Weaviate.Client.ExportClient 94% 47.8%
Weaviate.Client.Factory 100%
Weaviate.Client.Generate 100%
Weaviate.Client.GenerateClient 12.6% 32.6%
Weaviate.Client.GenerateClientHybridExtensions 0%
Weaviate.Client.GenerativeConfigFactory 11.5% 100%
Weaviate.Client.GenerativeProviderFactory 0.9%
Weaviate.Client.GroupsClient 100%
Weaviate.Client.GroupsOidcClient 47.8%
Weaviate.Client.Grpc.BatchStreamContext 100%
Weaviate.Client.Grpc.BatchStreamWrapper 75.3% 58.9%
Weaviate.Client.Grpc.LoggingInterceptor 0% 0%
Weaviate.Client.Grpc.RetryInterceptor 41.6% 37.5%
Weaviate.Client.Grpc.WeaviateGrpcClient 66.6% 50.6%
Weaviate.Client.Grpc.WeaviateGrpcServerException 0%
Weaviate.Client.Internal.AutoArray`1 61.9% 50%
Weaviate.Client.Internal.AutoArrayBuilder 100% 100%
Weaviate.Client.Internal.BatchStreamAcks 100%
Weaviate.Client.Internal.BatchStreamBackoff 0%
Weaviate.Client.Internal.BatchStreamError 0%
Weaviate.Client.Internal.BatchStreamOutOfMemory 0%
Weaviate.Client.Internal.BatchStreamResults 100%
Weaviate.Client.Internal.BatchStreamSuccess 100%
Weaviate.Client.Internal.ExceptionHelper 72.1% 61.5%
Weaviate.Client.Internal.HttpLoggingHandler 0% 0%
Weaviate.Client.Internal.KeySortedList`2 50%
Weaviate.Client.Internal.MultiKeySortedList`2 0% 0%
Weaviate.Client.Internal.ObjectHelper 48% 34.8%
Weaviate.Client.Internal.RetryHandler 49% 50%
Weaviate.Client.Internal.TimeoutHelper 72.9% 44.4%
Weaviate.Client.Internal.VersionGuard 92.3% 88.8%
Weaviate.Client.Models.Aggregate 100%
Weaviate.Client.Models.AggregateGroupByResult 26.1% 8.4%
Weaviate.Client.Models.AggregateResult 50% 31.1%
Weaviate.Client.Models.Alias 100%
Weaviate.Client.Models.AliasesResource 100%
Weaviate.Client.Models.AndNestedFilter 50%
Weaviate.Client.Models.AsciiFoldConfig 100%
Weaviate.Client.Models.Backup 66.6%
Weaviate.Client.Models.BackupBackend 20%
Weaviate.Client.Models.BackupClientConfig 100%
Weaviate.Client.Models.BackupCreateOperation 100%
Weaviate.Client.Models.BackupCreateRequest 100%
Weaviate.Client.Models.BackupOperationBase 67.7% 67.8%
Weaviate.Client.Models.BackupRestoreOperation 100%
Weaviate.Client.Models.BackupRestoreRequest 100%
Weaviate.Client.Models.BackupsResource 100%
Weaviate.Client.Models.BackupStatusExtensions 78.5% 52.5%
Weaviate.Client.Models.BatchInsertRequest 52.1%
Weaviate.Client.Models.BatchInsertResponse 80%
Weaviate.Client.Models.BatchInsertResponseEntry 100%
Weaviate.Client.Models.BatchReferenceReturn 29% 0%
Weaviate.Client.Models.BM25Config 61.1% 66.6%
Weaviate.Client.Models.Bm25ConfigUpdate 60% 50%
Weaviate.Client.Models.BM25Operator 100%
Weaviate.Client.Models.Boost 76.4% 44.4%
Weaviate.Client.Models.ClusterNode 30.7%
Weaviate.Client.Models.ClusterNodeVerbose 23% 0%
Weaviate.Client.Models.CollectionConfig 69.5% 57.1%
Weaviate.Client.Models.CollectionConfigCommon 67.9% 59.3%
Weaviate.Client.Models.CollectionConfigExport 0% 0%
Weaviate.Client.Models.CollectionsResource 100%
Weaviate.Client.Models.CollectionUpdate 42.2% 50%
Weaviate.Client.Models.CurrentUserInfo 80%
Weaviate.Client.Models.DatabaseUser 55.5%
Weaviate.Client.Models.DataReference 100% 50%
Weaviate.Client.Models.DataResource 100%
Weaviate.Client.Models.DataTypeExtensions 0% 0%
Weaviate.Client.Models.DeleteManyObjectResult 100%
Weaviate.Client.Models.DeleteManyResult 100%
Weaviate.Client.Models.Diversity 100%
Weaviate.Client.Models.DynamicDto 0%
Weaviate.Client.Models.EmptyBackend 33.3%
Weaviate.Client.Models.EmptyStringEnumConverter`1 86.9% 66.6%
Weaviate.Client.Models.Export 61.5%
Weaviate.Client.Models.ExportBackend 0%
Weaviate.Client.Models.ExportClientConfig 100%
Weaviate.Client.Models.ExportCreateRequest 100%
Weaviate.Client.Models.ExportOperation 100%
Weaviate.Client.Models.ExportOperationBase 72.8% 67.8%
Weaviate.Client.Models.ExportStatusExtensions 63.6% 41.6%
Weaviate.Client.Models.FilesystemBackend 100%
Weaviate.Client.Models.Filter 60.8% 40%
Weaviate.Client.Models.Filter`1 50% 50%
Weaviate.Client.Models.FlatDto 100%
Weaviate.Client.Models.FlexibleConverter`1 15.9% 9.1%
Weaviate.Client.Models.FlexibleStringConverter 46.1% 41.6%
Weaviate.Client.Models.Generative.Providers 0.5%
Weaviate.Client.Models.GenerativeConfig 14.6%
Weaviate.Client.Models.GenerativeConfigSerialization 49.4% 57.5%
Weaviate.Client.Models.GenerativeDebug 0%
Weaviate.Client.Models.GenerativeGroupByObject 100%
Weaviate.Client.Models.GenerativeGroupByResult 25%
Weaviate.Client.Models.GenerativePrompt 100%
Weaviate.Client.Models.GenerativeProvider 83.3%
Weaviate.Client.Models.GenerativeReply 100%
Weaviate.Client.Models.GenerativeResult 20% 0%
Weaviate.Client.Models.GenerativeWeaviateGroup 100%
Weaviate.Client.Models.GenerativeWeaviateObject 100%
Weaviate.Client.Models.GenerativeWeaviateResult 100%
Weaviate.Client.Models.GeoCoordinate 100%
Weaviate.Client.Models.GeoCoordinateConstraint 0%
Weaviate.Client.Models.GroupByObject 100%
Weaviate.Client.Models.GroupByRequest 100%
Weaviate.Client.Models.GroupByResult 16.6%
Weaviate.Client.Models.GroupByResult`2 100%
Weaviate.Client.Models.GroupedTask 100%
Weaviate.Client.Models.GroupRoleAssignment 0%
Weaviate.Client.Models.GroupsResource 100%
Weaviate.Client.Models.HFreshDto 100%
Weaviate.Client.Models.HnswDto 100%
Weaviate.Client.Models.HybridNearTextBuilder 0%
Weaviate.Client.Models.HybridNearVectorBuilder 0%
Weaviate.Client.Models.HybridVectorInput 78.5% 85.7%
Weaviate.Client.Models.HybridVectorInputBuilder 0%
Weaviate.Client.Models.InvertedIndexConfig 44.5% 29.1%
Weaviate.Client.Models.InvertedIndexConfigUpdate 71.4% 50%
Weaviate.Client.Models.JsonConverterEmptyCollectionAsNull 73.6% 50%
Weaviate.Client.Models.Metadata 100%
Weaviate.Client.Models.MetadataQuery 81.8%
Weaviate.Client.Models.MetaInfo 92.8% 80%
Weaviate.Client.Models.Metrics 84.8% 60%
Weaviate.Client.Models.ModalityFields 50% 50%
Weaviate.Client.Models.ModelsToDtoExtensions 100% 90%
Weaviate.Client.Models.ModuleConfigList 0% 0%
Weaviate.Client.Models.Move 100%
Weaviate.Client.Models.MultiTenancyConfig 100%
Weaviate.Client.Models.MultiTenancyConfigUpdate 60%
Weaviate.Client.Models.MultiVectorDto 100%
Weaviate.Client.Models.MultiVectorEncodingDto 100%
Weaviate.Client.Models.MuveraDto 100% 100%
Weaviate.Client.Models.NamedVector 100% 100%
Weaviate.Client.Models.NamespacesResource 100%
Weaviate.Client.Models.NearTextBuilder 36.2%
Weaviate.Client.Models.NearTextInput 50%
Weaviate.Client.Models.NearVectorBuilder 0%
Weaviate.Client.Models.NearVectorInput 45.4%
Weaviate.Client.Models.NestedFilter 100%
Weaviate.Client.Models.NodesResource 50%
Weaviate.Client.Models.NodeStatusExtensions 0% 0%
Weaviate.Client.Models.NotNestedFilter 100%
Weaviate.Client.Models.ObjectReference 80%
Weaviate.Client.Models.ObjectStorageBackend 0%
Weaviate.Client.Models.ObjectTTLConfig 97.5%
Weaviate.Client.Models.ObjectTTLConfigUpdate 89.6% 26.9%
Weaviate.Client.Models.OrNestedFilter 100%
Weaviate.Client.Models.PermissionResourceExtensions 80.5% 33.3%
Weaviate.Client.Models.Permissions 70% 59.3%
Weaviate.Client.Models.PermissionScope 100%
Weaviate.Client.Models.PhoneNumber 77.7%
Weaviate.Client.Models.Property 86.4% 62.5%
Weaviate.Client.Models.Property`1 100%
Weaviate.Client.Models.PropertyFilter 74.4% 50%
Weaviate.Client.Models.PropertyHelper 67.8% 53.4%
Weaviate.Client.Models.PropertyIndexTypeExtensions 50% 25%
Weaviate.Client.Models.PropertyUpdate 25%
Weaviate.Client.Models.QueryProfile 100%
Weaviate.Client.Models.QueryReference 100%
Weaviate.Client.Models.Reference 100%
Weaviate.Client.Models.ReferenceFilter 100%
Weaviate.Client.Models.ReferenceUpdate 0%
Weaviate.Client.Models.ReplicateRequest 100%
Weaviate.Client.Models.ReplicateResource 100%
Weaviate.Client.Models.ReplicationAsyncConfig 100%
Weaviate.Client.Models.ReplicationClientConfig 100%
Weaviate.Client.Models.ReplicationConfig 100%
Weaviate.Client.Models.ReplicationConfigUpdate 44.4%
Weaviate.Client.Models.ReplicationOperation 70% 50%
Weaviate.Client.Models.ReplicationOperationError 0%
Weaviate.Client.Models.ReplicationOperationStatus 37.5% 0%
Weaviate.Client.Models.ReplicationOperationTracker 68% 54.5%
Weaviate.Client.Models.Rerank 100%
Weaviate.Client.Models.Reranker 15.3%
Weaviate.Client.Models.RerankerConfigSerialization 56.8% 55%
Weaviate.Client.Models.RoleInfo 100%
Weaviate.Client.Models.RolesResource 100%
Weaviate.Client.Models.SearchProfile 100%
Weaviate.Client.Models.ShardInfo 100%
Weaviate.Client.Models.ShardingConfig 100%
Weaviate.Client.Models.ShardProfile 100%
Weaviate.Client.Models.ShardProgress 33.3%
Weaviate.Client.Models.ShardStatusExtensions 100% 50%
Weaviate.Client.Models.SimpleTargetVectors 100%
Weaviate.Client.Models.SinglePrompt 100%
Weaviate.Client.Models.Sort 100% 50%
Weaviate.Client.Models.SortExtensions 100%
Weaviate.Client.Models.StopwordConfig 61.9% 62.5%
Weaviate.Client.Models.StopwordsConfigUpdate 57.1% 50%
Weaviate.Client.Models.TargetVectors 27.6% 0%
Weaviate.Client.Models.Tenant 38.8% 13.3%
Weaviate.Client.Models.TenantsResource 100%
Weaviate.Client.Models.TextAnalyzerConfig 100%
Weaviate.Client.Models.TimeFilter 75% 25%
Weaviate.Client.Models.TokenizeMapping 77.2% 60.4%
Weaviate.Client.Models.TokenizeResult 100%
Weaviate.Client.Models.Typed.AggregateGroupByResult`1 0% 0%
Weaviate.Client.Models.Typed.AggregatePropertyMapper 0% 0%
Weaviate.Client.Models.Typed.AggregateResult`1 0%
Weaviate.Client.Models.Typed.BooleanMetricsAttribute 0%
Weaviate.Client.Models.Typed.DateMetricsAttribute 0%
Weaviate.Client.Models.Typed.GenerativeGroupByObject`1 0%
Weaviate.Client.Models.Typed.GenerativeGroupByResult`1 0%
Weaviate.Client.Models.Typed.GenerativeWeaviateGroup`1 0%
Weaviate.Client.Models.Typed.GenerativeWeaviateObject`1 0%
Weaviate.Client.Models.Typed.GenerativeWeaviateResult`1 0%
Weaviate.Client.Models.Typed.GroupByObject`1 0%
Weaviate.Client.Models.Typed.GroupByResult`1 0%
Weaviate.Client.Models.Typed.IntegerMetricsAttribute 0%
Weaviate.Client.Models.Typed.MetricsExtractor 0% 0%
Weaviate.Client.Models.Typed.NumberMetricsAttribute 0%
Weaviate.Client.Models.Typed.TextMetricsAttribute 0%
Weaviate.Client.Models.Typed.TypedResultConverter 12% 7.6%
Weaviate.Client.Models.Typed.WeaviateGroup`2 0%
Weaviate.Client.Models.Typed.WeaviateObject`1 47.3% 37.5%
Weaviate.Client.Models.TypedBase`1 70.5%
Weaviate.Client.Models.TypedGuid 66.6%
Weaviate.Client.Models.TypedValue`1 80%
Weaviate.Client.Models.User 0%
Weaviate.Client.Models.UserMetadata 0%
Weaviate.Client.Models.UserRoleAssignment 100%
Weaviate.Client.Models.UsersResource 100%
Weaviate.Client.Models.Vector 32.8% 18.7%
Weaviate.Client.Models.VectorBuilder 0% 0%
Weaviate.Client.Models.VectorConfig 82.7% 58.3%
Weaviate.Client.Models.VectorConfigList 59.3% 60%
Weaviate.Client.Models.VectorConfigUpdate 50%
Weaviate.Client.Models.VectorIndex 98%
Weaviate.Client.Models.VectorIndexConfig 100%
Weaviate.Client.Models.VectorIndexConfigUpdate 68.4% 33.3%
Weaviate.Client.Models.VectorIndexConfigUpdateDynamic 0% 0%
Weaviate.Client.Models.VectorIndexConfigUpdateFlat 40%
Weaviate.Client.Models.VectorIndexConfigUpdateHNSW 52.9%
Weaviate.Client.Models.VectorIndexMappingExtensions 89.1% 60.6%
Weaviate.Client.Models.VectorIndexSerialization 58.2% 58.3%
Weaviate.Client.Models.VectorInputBuilderFactories 50% 50%
Weaviate.Client.Models.Vectorizer 14% 0%
Weaviate.Client.Models.VectorizerAttribute 100%
Weaviate.Client.Models.VectorizerConfig 64.1% 56.2%
Weaviate.Client.Models.VectorizerRegistry 68.9% 71.4%
Weaviate.Client.Models.Vectorizers.VectorizerConfigFactory 58% 62.5%
Weaviate.Client.Models.VectorMulti`1 38.8% 23%
Weaviate.Client.Models.VectorQuery 45% 50%
Weaviate.Client.Models.Vectors 31.2% 100%
Weaviate.Client.Models.VectorSearchInput 51.7% 16.6%
Weaviate.Client.Models.VectorSingle`1 18.1% 0%
Weaviate.Client.Models.WeaviateGroup`1 80%
Weaviate.Client.Models.WeaviateObject 88.8%
Weaviate.Client.Models.WeaviateObjectExtensions 56.5% 50%
Weaviate.Client.Models.WeaviateResult 100%
Weaviate.Client.Models.WeaviateResult`1 100%
Weaviate.Client.Models.WeightedField 0%
Weaviate.Client.Models.WeightedFields 0% 0%
Weaviate.Client.Models.WeightedTargetVectors 100% 100%
Weaviate.Client.NearMediaBuilder 0% 0%
Weaviate.Client.NearMediaInput 0%
Weaviate.Client.NodesClient 87.5% 50%
Weaviate.Client.OAuthConfig 71.4%
Weaviate.Client.OAuthTokenService 39.2% 18.7%
Weaviate.Client.QueryClient 47.1% 40%
Weaviate.Client.QueryClientHybridExtensions 0% 0%
Weaviate.Client.QueryClientNearTextExtensions 0% 0%
Weaviate.Client.ReplicationsClient 88.5% 56.6%
Weaviate.Client.RequiresWeaviateVersionAttribute 100%
Weaviate.Client.RerankerConfigFactory 14.2% 100%
Weaviate.Client.Rest.EnumMemberJsonConverter`1 0% 0%
Weaviate.Client.Rest.EnumMemberJsonConverterFactory 0%
Weaviate.Client.Rest.HttpResponseMessageExtensions 82.9% 62.5%
Weaviate.Client.Rest.InvalidEnumWireFormatException 0%
Weaviate.Client.Rest.WeaviateEndpoints 79.1% 75.8%
Weaviate.Client.Rest.WeaviateRestClient 88.5% 53.2%
Weaviate.Client.Rest.WeaviateRestClientException 0% 0%
Weaviate.Client.Rest.WeaviateRestServerException 0% 0%
Weaviate.Client.Rest.WeaviateUnexpectedStatusCodeException 100%
Weaviate.Client.RetryPolicy 50% 42.8%
Weaviate.Client.RolesClient 90.3% 50%
Weaviate.Client.Serialization.Converters.BlobHashPropertyConverter 10.7% 0%
Weaviate.Client.Serialization.Converters.BlobPropertyConverter 58.8% 37.5%
Weaviate.Client.Serialization.Converters.BoolPropertyConverter 64% 40%
Weaviate.Client.Serialization.Converters.DatePropertyConverter 31% 21%
Weaviate.Client.Serialization.Converters.GeoPropertyConverter 28.3% 10.5%
Weaviate.Client.Serialization.Converters.IntPropertyConverter 49.2% 26.3%
Weaviate.Client.Serialization.Converters.NumberPropertyConverter 56.8% 23.5%
Weaviate.Client.Serialization.Converters.ObjectPropertyConverter 18% 7.3%
Weaviate.Client.Serialization.Converters.PhonePropertyConverter 14.4% 5.2%
Weaviate.Client.Serialization.Converters.TextPropertyConverter 36.3% 20.8%
Weaviate.Client.Serialization.Converters.UuidPropertyConverter 61.1% 37.5%
Weaviate.Client.Serialization.PropertyBag 0% 0%
Weaviate.Client.Serialization.PropertyConverterBase 23% 11.9%
Weaviate.Client.Serialization.PropertyConverterRegistry 73.7% 65.5%
Weaviate.Client.TenantsClient 84.5% 37.5%
Weaviate.Client.TokenizeClient 85.1% 75%
Weaviate.Client.Typed.TypedCollectionClient`1 91.1% 50%
Weaviate.Client.Typed.TypedDataClient`1 49%
Weaviate.Client.Typed.TypedGenerateClient`1 0.8% 0%
Weaviate.Client.Typed.TypedGenerateClientHybridExtensions 0%
Weaviate.Client.Typed.TypedQueryClient`1 9.9% 100%
Weaviate.Client.Typed.TypedQueryClientHybridExtensions 0%
Weaviate.Client.UsersClient 89.4% 66.6%
Weaviate.Client.UsersDatabaseClient 100% 62.5%
Weaviate.Client.UsersOidcClient 4.5%
Weaviate.Client.Validation.TypeValidationException 0%
Weaviate.Client.Validation.TypeValidator 50% 48.6%
Weaviate.Client.Validation.ValidationError 83.3%
Weaviate.Client.Validation.ValidationResult 62.5% 50%
Weaviate.Client.Validation.ValidationWarning 0%
Weaviate.Client.ValidationExtensions 80% 100%
Weaviate.Client.VectorizerFactory 9.5% 50%
Weaviate.Client.VectorizerFactoryMulti 5.7%
Weaviate.Client.WeaviateAuthenticationException 100% 100%
Weaviate.Client.WeaviateAuthorizationException 100% 100%
Weaviate.Client.WeaviateBackupConflictException 100%
Weaviate.Client.WeaviateBadRequestException 0% 0%
Weaviate.Client.WeaviateClient 59.8% 48%
Weaviate.Client.WeaviateClientBuilder 56.6% 50%
Weaviate.Client.WeaviateClientBuilderExtensions 0% 0%
Weaviate.Client.WeaviateClientException 33.3%
Weaviate.Client.WeaviateCollectionLimitReachedException 0% 0%
Weaviate.Client.WeaviateConflictException 100%
Weaviate.Client.WeaviateDefaults 100%
Weaviate.Client.WeaviateException 66.6%
Weaviate.Client.WeaviateExtensions 78.3% 53.4%
Weaviate.Client.WeaviateExternalModuleProblemException 0% 0%
Weaviate.Client.WeaviateFeatureNotSupportedException 0% 0%
Weaviate.Client.WeaviateModuleNotAvailableException 0% 0%
Weaviate.Client.WeaviateNotFoundException 14.8% 0%
Weaviate.Client.WeaviateServerException 66.6%
Weaviate.Client.WeaviateTimeoutException 0% 0%
Weaviate.Client.WeaviateUnprocessableEntityException 100% 100%
Weaviate.Client.WeaviateVersionMismatchException 76.9% 50%
Weaviate.Client.Analyzers - 0%
Name Line Branch
Weaviate.Client.Analyzers 0% 0%
Weaviate.Client.Analyzers.AggregatePropertySuffixAnalyzer 0% 0%
Weaviate.Client.Analyzers.AutoArrayUsageAnalyzer 0% 0%
Weaviate.Client.Analyzers.HybridSearchNullParametersAnalyzer 0% 0%
Weaviate.Client.Analyzers.RequiresVersionEnsureCallAnalyzer 0% 0%
Weaviate.Client.Analyzers.VectorizerFactoryAnalyzer 0% 0%
Weaviate.Client.VectorData - 50.3%
Name Line Branch
Weaviate.Client.VectorData 50.3% 31.2%
Weaviate.Client.VectorData.DependencyInjection.WeaviateVectorDataServiceCol
lectionExtensions
0% 0%
Weaviate.Client.VectorData.Filters.WeaviateFilterTranslator 29.2% 19.5%
Weaviate.Client.VectorData.Mapping.AttributeBasedRecordMapper`1 59.7% 50%
Weaviate.Client.VectorData.Mapping.DataPropertyInfo 100%
Weaviate.Client.VectorData.Mapping.DynamicRecordMapper 0% 0%
Weaviate.Client.VectorData.Mapping.RecordPropertyModel 54.9% 43.1%
Weaviate.Client.VectorData.Mapping.VectorDataSchemaBuilder 41.3% 18.7%
Weaviate.Client.VectorData.Mapping.VectorPropertyInfo 85.7%
Weaviate.Client.VectorData.WeaviateVectorStore 61.2% 33.3%
Weaviate.Client.VectorData.WeaviateVectorStoreCollection`2 71.3% 44.7%
Weaviate.Client.VectorData.WeaviateVectorStoreCollectionOptions 0%
Weaviate.Client.VectorData.WeaviateVectorStoreOptions 0%

@dirkkul

dirkkul commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Hey,

VectorizeCollectionName

These are not available for Multivector and we simply have not removed them from python to not create a breaking change

…ories

Corrects 55b0693, which folded a vectorizeCollectionName parameter into both
Gemini overloads alongside dimensions. dimensions was right; this was not.

No multi2vec module reads vectorizeClassName server-side, so the parameter
did nothing. Python's multi2vec_google_gemini does not expose it, and neither
does any other multi2vec_* factory — f8a6d4f1 documents it as having no
effect across all of them. #367 removed it from Multi2VecTwelveLabs two PRs
ago for the same reason, so keeping it here would have contradicted a
decision already made on this branch's own predecessor.

Confirmed against the live 1.39.0 server: creating the collection without the
key stores no vectorizeClassName and the server defaults nothing back in, so
the integration test now asserts null there instead of false.

The property itself stays on the Multi2VecGoogle record: it is shipped API
and inherited by the Gemini path, so the factory pins it to null explicitly
(which the WEAVIATE002 analyzer requires) rather than dropping it.

Only the two Unshipped signature lines are rewritten, with no *REMOVED*
markers: the parameter never shipped, it was added earlier on this same
branch. The *REMOVED* entries above them still describe the genuinely
removed pre-PR signatures.

The Vertex Multi2VecGoogle overloads are deliberately untouched — they
carried vectorizeCollectionName in PublicAPI.Shipped.txt before this branch,
so removing it there is a breaking change and a separate decision.
…izers

A maintainer confirmed on #368 that vectorizeCollectionName is not available
for multivector modules, and that python only keeps it to avoid a breaking
change. The server bears that out: no multi2vec-* or multi2multivec-* module
has a VectorizeClassName() accessor, own or via an embedded BaseClassSettings.
They register "vectorizeClassName" as a class-config default in config.go and
never read it back — only usecases/modulecomponents/vectorizer/object_texts.go
consumes it, behind an icheck interface no multivector settings type
implements.

So the eight multivector records get [Obsolete] on the property, mirroring
python's "Deprecated, has no effect", with the XML docs saying the same. The
property stays: removing it would break callers.

text2vec-* is untouched — the setting is real there, and the digitalocean
test asserts vectorizeClassName:false deliberately.

text2multivec-jinaai is deliberately left alone despite the name. Its class
settings embed basesettings.BaseClassSettings, which supplies the
VectorizeClassName() accessor that base_class_settings.go actually calls, so
the setting is live for it. It is a text vectorizer that happens to emit
multiple vectors, not a multivector-input module.

The factory parameters could not be marked: [Obsolete] is not valid on a
parameter (CS0592 — it is only valid on class, struct, enum, constructor,
method, property, indexer, field, event, interface and delegate), verified
with the compiler rather than assumed. Their <param> docs carry python's
wording instead, which is what python does too — f8a6d4f1 is documentation
only. Consumers still get a real CS0618 when they read or assign the
property, including on a config read back from the server.

The eighteen factory assignments the client itself must keep — WEAVIATE002
requires every public property to be initialised in a vectorizer factory —
are suppressed one line at a time with scoped pragmas and a reason, not at
file or project level. The one test that asserts on the property is
suppressed the same way rather than deleted, since the assertion is the point.
The suppressions added in a1430ec carried a standalone comment line above
each pragma, repeated verbatim sixteen times. The house form puts a terse
reason as a trailing comment on the pragma itself, on both the disable and
the restore — Models/Extensions.cs:116-118 is the exact analogue, an obsolete
property assigned inside an object initializer.

Also drops two comments that had become restatements once the property
carried [Obsolete]: the Gemini factories now note only the part the attribute
does not say — that they omit the parameter their Vertex siblings expose —
and the unit test drops a clause that repeated the obsolete message while
keeping why the key still serializes here when Multi2VecTwelveLabs drops it.
The suppression reason in the integration test moves onto the pragma too,
where it reads as the reason rather than as a third comment line.

No behaviour change: 20 lines out, 3 in.
Boost (#355) landed on main and overlapped this branch in two files.

gRPC/Search.Builders.cs auto-merged: boost added BuildBoost and its call
sites, we added the deepseek runtime-provider mapping, and the two do not
touch the same lines. Verified structurally rather than by eye — stripping
main's side from the merged file reproduces our base->branch delta exactly,
and stripping ours reproduces main's.

PublicAPI.Unshipped.txt was the only real conflict. Boost rewrote ~50
overload signatures, so it removed 102 base lines and added 132; we added
106 and removed none. The two sets are disjoint: nothing we added was
removed by boost, nothing boost added was removed by us. Resolved as the
union — boost's file plus our 106 lines — and then handed to the analyzer
rather than trusted: RS0016 192, RS0017 16, RS0025 0, all identical to what
origin/main reports on its own, so our entries introduce no missing or stale
declarations. PublicAPI.Shipped.txt did not move between the merge base and
origin/main, so our *REMOVED* lines still name signatures that exist.

Unit tests account for both sides exactly: main 946 -> 985 with boost's 39,
and 985 -> 997 with our 12.
The gate comment claimed 1.37.0 was the first server to accept the field; the
wire field has existed since 1.34.18. Keep the 1.37.0 gate as the documented
feature floor, matching python, and say so.

The read side has a different floor: servers only return the base id from
1.37.6, so on older ones a null does not mean the backup is non-incremental.
Say that on the property, where deleting the base backup is the hazard.

Collapse the duplicated create/list tests into theories.
The gating commit added a comment saying every scalar is checked against its
Has* flag, but Count was left ungated in all five branches, so an unrequested
count still read 0 - the defect the commit set out to fix. Property.Count is
already long?, so gating costs no API change.

Correct the Boolean member docs: when nothing matches the server does send all
four, so null means it did not send the value, not that nothing matched.

Drop two ConvertToNumeric overloads left unreachable by the nullable callers,
and update the accessor docs, which still showed the members non-nullable.
C# cannot mark a parameter [Obsolete] (CS0592), so the sweep marked only the
property - and every assignment to it sat behind a pragma inside the library.
A caller passing vectorizeCollectionName: true got no diagnostic at all, which
is the one audience the deprecation was for. The cost was 38 suppression lines.

Python never surfaced vectorize_collection_name on its multivector factories,
so there is nothing to deprecate toward; converging on that is a deliberate
breaking change and does not belong in this PR.

Keeps the type-level [Obsolete] on the Multi2VecGoogleGemini shim, which is
real, and 55b0693's Gemini collapse.

Also make the Gemini serialization tests assert absence instead of an explicit
null, which only tested the test's own serializer options.
Records the additions, the fixes and the breaking changes, including the two
the description had not called out: Multi2VecGoogleGemini.Model is removed with
no replacement under that name, and BackupCreateRequest went from six positional
parameters to seven.

Corrects three entries that still advertise Multi2VecGoogleGemini as a working
vectorizer; the 1.0.1 entry called it new when it could never create a
collection. The original text stays, with the correction after it.
multi2vec-google has no apiEndpoint before 1.34.20 (introduced in 4862194,
in no 1.32.x or 1.33.x tag), so those servers fall through to the Vertex
mandatory check and reject the Gemini config for missing projectId/location.
RequireModule does not cover this: the module is on every lane, only the
Gemini config shape is version-dependent.

Verified on real servers: without the gate 1.32.27 reproduces the CI error;
with it the test skips there and still runs on 1.34.20.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for new generative-deepseek module

2 participants