Skip to content

Chroma v2 API, pull requests 80 and 82, and fixes: continued in ChromaDotNet.Client - #84

Closed
Laurianti wants to merge 587 commits into
ssone95:masterfrom
ChromaDotNet:main
Closed

Laurianti wants to merge 587 commits into
ssone95:masterfrom
ChromaDotNet:main

Conversation

@Laurianti

@Laurianti Laurianti commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Status (October 23, 2026): ChromaDB.Client is deprecated on NuGet in favor of ChromaDotNet.Client, and since #85 the README says that the development continues in ChromaDotNet/ChromaDB.Client. Thanks, @cincuranet! This pull request is closed and stays here for reference. Issues and contributions are welcome there.


This pull request collected the work of ChromaDotNet/ChromaDB.Client: the pull requests #80 by @inlineHamed and #82 by @richlander, which move the client to the Chroma v2 API, the fixes for the issues below, and new features.

ChromaDotNet.Client supports the whole v2 API and Chroma Cloud, keeps the v1 API for the servers that have only it, and is tested against Chroma 0.4.10 to 1.5.9. It is used by the AI and Aspire Community Toolkits of the .NET Foundation. The migration guide shows how to move from ChromaDB.Client.

Fixes #69 (opened by @cincuranet)
Fixes #78 (reported by @Lingchar, with the fix proposed there)
Fixes #79 (reported by @hannahhaken)
Fixes #81 (reported by @mubarak0443)
Fixes #76 (opened by @luisquintanilla)
Fixes #83 (reported by @Chris-Maina)
Fixes #5
Fixes #33
Fixes #6

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Fork-specific branding and package instructions contradict the target repository’s package identity.

Review effort: Balanced
Findings: 2 Low severity

Open (2)
What changed in this PR

Migrates the client to Chroma API v2 while improving compatibility, cancellation, error handling, dependency injection, and CI coverage.

Changes:

  • Migrates endpoints and defaults to API v2.
  • Adds cancellation support and fixes response/request handling.
  • Expands tests and CI across Chroma and .NET versions.
File Description
v2-migration/​MIGRATION_GUIDE_V2.md Adds migration guidance.
Samples/​ChromaDB.Client.Sample/​Program.cs Uses the v2 endpoint.
README.md Documents compatibility and migration.
ChromaDB.Client/​Models/​Responses/​GeneralError.cs Supports v2 error fields.
ChromaDB.Client/​Models/​Responses/​CollectionEntriesQueryResponse.cs Handles optional distances and data.
ChromaDB.Client/​Models/​Responses/​CollectionEntriesGetResponse.cs Makes response data optional.
ChromaDB.Client/​Models/​Requests/​CollectionModifyRequest.cs Corrects modify field names.
ChromaDB.Client/​Common/​HttpClientHelpers.cs Adds cancellation, URI construction, and error handling.
ChromaDB.Client/​Common/​CollectionQueryEntryMapper.cs Maps optional distances.
ChromaDB.Client/​Common/​ClientConstants.cs Changes the default endpoint to v2.
ChromaDB.Client/​Common/​ChromaHttpClient.cs Avoids mutating shared HTTP clients.
ChromaDB.Client/​ChromaDB.Client.csproj Updates version and package metadata.
ChromaDB.Client/​ChromaCollectionQueryEntry.cs Makes distance nullable.
ChromaDB.Client/​ChromaCollectionClient.cs Migrates collection operations to v2.
ChromaDB.Client/​ChromaClient.cs Migrates client operations to v2.
ChromaDB.Client.Tests/​TestContainer/​ChromaDBBuilder.cs Makes the tested Chroma image configurable.
ChromaDB.Client.Tests/​DependencyInjectionTests.cs Tests DI registration.
ChromaDB.Client.Tests/​CollectionClientTests.cs Strengthens modify and embedding tests.
ChromaDB.Client.Tests/​CollectionClientQueryTests.cs Tests omitted distances.
ChromaDB.Client.Tests/​CollectionClientCUDTests.cs Adapts CRUD tests across server versions.
ChromaDB.Client.Tests/​ClientTests.cs Tests shared HTTP clients and errors.
ChromaDB.Client.Tests/​ClientResetTests.cs Handles version-specific reset settings.
ChromaDB.Client.Tests/​ClientAuthTests.cs Skips removed Chroma 1.x authentication.
ChromaDB.Client.Tests/​ChromaTestsBase.cs Adds version-aware test helpers.
ChromaDB.Client.Tests/​ChromaDB.Client.Tests.csproj Tests alternate client target frameworks.
ChromaDB.Client.Tests/​CancellationTests.cs Verifies cancellation propagation.
ChromaDB.Client.DependencyInjection/​ChromaDB.Client.DependencyInjection.csproj Updates DI package metadata.
ChromaDB.Client.DependencyInjection/​ChromaClientExtensions.cs Registers configuration options.
.github/​workflows/​ci.yml Adds server matrix, packaging, and publishing updates.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread README.md Outdated
Comment thread v2-migration/MIGRATION_GUIDE_V2.md
DeleteAllAsync, FromDictionary for documents, empty metadata as null, version 2.16.0
…exts

An IEmbeddingGenerator of Microsoft.Extensions.AI computes the embeddings of the documents written without them and of the query texts, as an embedding function does in the Python client. A new collection with the generator of the default embedding function of Chroma declares "default". Only the .NET 8 and .NET Framework builds have the new API. Version 2.17.0 for the client and DI.
WithEmbeddingGenerator: embeddings from an IEmbeddingGenerator, query texts and the default embedding function, version 2.17.0
Match the literal dots of the signing identity in the Cosign command
… version, and check it in the CI

The release notes of ChromaDotNet.Client and ChromaDotNet.Client.DependencyInjection were still the ones of 2.14.0 in the
packages 2.15.0, 2.16.0 and 2.17.0. They now link the GitHub release of VersionPrefix, so they follow every release.
A CI step after Pack fails when a package does not link the release of its version: it fails on the packages of main
and passes on these.
…ent, before the request

Chroma keeps the document of a record in the metadata key chroma:document. A text there sets the document, and goes as it is.
Another value, like a number, a Boolean, a list or a null in an update or an upsert, makes Chroma 1.x fail every add and get
of the server until it restarts; AddAsync, UpdateAsync and UpsertAsync now throw an ArgumentException for it before the
request. The other keys with the prefix chroma: go as before: Chroma filters on them and reads chroma:uri as the URI.
….x fail every write and read until it restarts

Measured in plain HTTP on 1.0.0 to 1.5.9; 0.4.10, 0.5.20 and 0.6.3 keep working.
…f chroma:document would write

WithDocumentCopyKey and WithDocumentDeletionKey add their metadata after the given one is checked. With the key chroma:document, a
deleted document would go as a null there, and a mark as true or null, which make Chroma 1.x fail like any value that is not a
text. AddAsync, UpdateAsync and UpsertAsync now throw an ArgumentException for them before the request; a copy of a text goes.
… a JSON string

A Guid, a DateTime, a DateTimeOffset and a byte[] go as JSON strings, so Chroma takes them as texts; the check threw for them.
It now writes the value with the options of the requests and looks at what comes out. A value the client cannot write goes on,
and fails as before when the request is written.
…reject one whose JSON cannot be told

Without JSON reflection, the type of a value that the JSON context does not list, like a list derived from List<int>, had no
JSON type info of its own: the check let it go, while the request wrote it as its List<int> base, an array. The check now
writes the value as an object, as the request does, and a value whose JSON cannot be told is not a text. The trimming and
NativeAOT test checks the derived list without reflection.
Reject a chroma:document that is not a text, KD-58, and release notes that link the release (2.17.1)
The test cancels 200 ms after the first attempt fails and expects the delay before the second one to be longer. With the full
jitter the delay of up to 10 minutes can be under 200 ms, about once in 3000 runs: the second attempt then goes first and the
read succeeds, which is right, and the test failed. ChromaReadRetries gets an internal Jitter that the tests can set; the test
sets it to 1, so the delay is 10 minutes and the cancellation always comes during it. The client and its API do not change.
The delay before a new attempt was a random time from zero to the cap, the smaller of MaxDelay and BaseDelay times 2 to the
attempts that went again before, so a read could go again at once. It is now a random time from MinDelay to the cap. A new
constructor takes MinDelay, from zero to BaseDelay; the constructor without it takes 0.8 times BaseDelay, the lower bound of the
jitter of Azure.Core, which is never above the base and is zero for a base of zero. The default waits 40 to 50 ms, then 40 to 100
and 40 to 200 ms; None does not change.
Just the address of the server works as the URI; the example takes the collection client from GetCollectionClient; the handlers
that rewrote v1 routes or read the tenant and the database from auth/identity can go, with WithTenantAndDatabaseFromIdentityAsync
for the credentials; dependency injection; and the behaviors that differ from 1.x: reads that go again, NaN distances, empty
metadata. QueryAsync returns the embeddings only when asked, as in 1.x.
…issing) and GetOrCreateCollectionClientAsync

GetCollectionClient(name or definition, createIfMissing: true) sends no request: its first operation gets or creates the
collection, with one request that the operations starting before it ends share, each with its own cancellation; a failure of it
comes from the first operation, and the next one asks again. GetOrCreateCollectionClientAsync(name or definition) sends the request
now, so its errors come from the call. Both keep the collection, and when it is deleted elsewhere they get or create it again and
run the operation again once, never a write that went in part. createIfMissing: false is GetCollectionClient(name).
…ions made from the services

The options of AddChromaClient come from a function of the default options, called at the registration, so they cannot read
IConfiguration or IOptions of the application. The new methods take a function of the IServiceProvider, called once when the client
or its options are first resolved; a null it returns throws an InvalidOperationException. They have their own names: an overload of
AddChromaClient would make AddChromaClient(_ => options) or AddChromaClient(null, builder => ...) ambiguous, and both compile as
before.
…r it was cancelled

When every operation waiting for the shared first read was cancelled and the read then failed, nothing let it go: the next operation
threw that failure again without a request, and only the one after it asked again. A failed or cancelled first read is now let go
when the next operation starts, so that operation sends a new request.
…ing metadata values

The creation called GetOrCreateCollectionAsync of the ChromaClient the collection client came from, so a client of WithMetadataValues
read the metadata of the collection the way of that ChromaClient: with an Inferred one, a date in the metadata came back as a
DateTime under Exact. The creation now goes with the ChromaHttpClient of the collection client, as the read by name does.
The first operation of a client that creates its collection started the shared request before it looked at its token, so an
operation cancelled before it was called, or GetOrCreateCollectionClientAsync with such a token, still created the collection. The
token is now checked first, and such an operation sends no request; the shared request stays independent of the waiters that are
cancelled later.
In FirstOperationsShareTheRequest the eight operations send their counts at the same time once the creation answers, and the fake
server added each request to a List<T>, which takes one writer at a time. Not seen in 5000 runs of the test, but such a write can
lose an entry or throw: the requests and the bodies are now recorded under a lock.
ChromaReadRetries.MinDelay, collections created when missing, options from the services, and the migration guide (2.18.0)
docs/embeddings.md starts with ChromaDotNet.Embeddings and a short example, run against the packages of nuget.org on Chroma 1.5.9,
with its limits and the SearchByText sample of ChromaDotNet.Local; the README links it next to ChromaDotNet.Local.
Docs: ChromaDotNet.Embeddings, the embeddings of the Python client
@Laurianti

Copy link
Copy Markdown
Contributor Author

Closing this. ChromaDB.Client is now deprecated on NuGet in favor of ChromaDotNet.Client, and since #85 the README says that the development continues in ChromaDotNet/ChromaDB.Client. Thanks, @cincuranet!

@Laurianti Laurianti closed this Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment