diff --git a/chromadb/__init__.py b/chromadb/__init__.py index fe7631bbec4..3869f8815fa 100644 --- a/chromadb/__init__.py +++ b/chromadb/__init__.py @@ -188,12 +188,12 @@ def HttpClient( settings.chroma_api_impl = "chromadb.api.fastapi.FastAPI" if settings.chroma_server_host and settings.chroma_server_host != host: - raise ValueError( + raise InvalidArgumentError( f"Chroma server host provided in settings[{settings.chroma_server_host}] is different to the one provided in HttpClient: [{host}]" ) settings.chroma_server_host = host if settings.chroma_server_http_port and settings.chroma_server_http_port != port: - raise ValueError( + raise InvalidArgumentError( f"Chroma server http port provided in settings[{settings.chroma_server_http_port}] is different to the one provided in HttpClient: [{port}]" ) settings.chroma_server_http_port = port @@ -239,12 +239,12 @@ async def AsyncHttpClient( settings.chroma_api_impl = "chromadb.api.async_fastapi.AsyncFastAPI" if settings.chroma_server_host and settings.chroma_server_host != host: - raise ValueError( + raise InvalidArgumentError( f"Chroma server host provided in settings[{settings.chroma_server_host}] is different to the one provided in HttpClient: [{host}]" ) settings.chroma_server_host = host if settings.chroma_server_http_port and settings.chroma_server_http_port != port: - raise ValueError( + raise InvalidArgumentError( f"Chroma server http port provided in settings[{settings.chroma_server_http_port}] is different to the one provided in HttpClient: [{port}]" ) settings.chroma_server_http_port = port diff --git a/chromadb/api/__init__.py b/chromadb/api/__init__.py index 2d0ff4e1c1f..e9d0f5aadf2 100644 --- a/chromadb/api/__init__.py +++ b/chromadb/api/__init__.py @@ -99,7 +99,7 @@ def delete_collection( name: The name of the collection to delete. Raises: - ValueError: If the collection does not exist. + InvalidArgumentError: If the collection does not exist. Examples: ```python @@ -388,8 +388,8 @@ def create_collection( Collection: The newly created collection. Raises: - ValueError: If the collection already exists and get_or_create is False. - ValueError: If the collection name is invalid. + InvalidArgumentError: If the collection already exists and get_or_create is False. + InvalidArgumentError: If the collection name is invalid. Examples: ```python @@ -422,7 +422,7 @@ def get_collection( Collection: The collection Raises: - ValueError: If the collection does not exist + InvalidArgumentError: If the collection does not exist Examples: ```python diff --git a/chromadb/api/async_api.py b/chromadb/api/async_api.py index 674f2d804f3..335dfbfeed8 100644 --- a/chromadb/api/async_api.py +++ b/chromadb/api/async_api.py @@ -91,7 +91,7 @@ async def delete_collection( name: The name of the collection to delete. Raises: - ValueError: If the collection does not exist. + InvalidArgumentError: If the collection does not exist. Examples: ```python @@ -380,8 +380,8 @@ async def create_collection( Collection: The newly created collection. Raises: - ValueError: If the collection already exists and get_or_create is False. - ValueError: If the collection name is invalid. + InvalidArgumentError: If the collection already exists and get_or_create is False. + InvalidArgumentError: If the collection name is invalid. Examples: ```python @@ -414,7 +414,7 @@ async def get_collection( Collection: The collection Raises: - ValueError: If the collection does not exist + InvalidArgumentError: If the collection does not exist Examples: ```python diff --git a/chromadb/api/async_client.py b/chromadb/api/async_client.py index f705fbebb32..547c32356e1 100644 --- a/chromadb/api/async_client.py +++ b/chromadb/api/async_client.py @@ -127,21 +127,21 @@ async def _validate_tenant_database(self, tenant: str, database: str) -> None: try: await self._admin_client.get_tenant(name=tenant) except httpx.ConnectError: - raise ValueError( + raise InvalidArgumentError( "Could not connect to a Chroma server. Are you sure it is running?" ) # Propagate ChromaErrors except ChromaError as e: raise e except Exception: - raise ValueError( + raise InvalidArgumentError( f"Could not connect to tenant {tenant}. Are you sure it exists?" ) try: await self._admin_client.get_database(name=database, tenant=tenant) except httpx.ConnectError: - raise ValueError( + raise InvalidArgumentError( "Could not connect to a Chroma server. Are you sure it is running?" ) diff --git a/chromadb/api/base_http_client.py b/chromadb/api/base_http_client.py index 5a1dd25aae6..45d37cd291d 100644 --- a/chromadb/api/base_http_client.py +++ b/chromadb/api/base_http_client.py @@ -18,11 +18,11 @@ class BaseHTTPClient: def _validate_host(host: str) -> None: parsed = urlparse(host) if "/" in host and parsed.scheme not in {"http", "https"}: - raise ValueError( + raise InvalidArgumentError( "Invalid URL. " f"Unrecognized protocol - {parsed.scheme}." ) if "/" in host and (not host.startswith("http")): - raise ValueError( + raise InvalidArgumentError( "Invalid URL. " "Seems that you are trying to pass URL as a host but without \ specifying the protocol. " diff --git a/chromadb/api/client.py b/chromadb/api/client.py index 0e171262da7..7a54f86c53d 100644 --- a/chromadb/api/client.py +++ b/chromadb/api/client.py @@ -100,14 +100,14 @@ def get_user_identity(self) -> UserIdentity: try: return self._server.get_user_identity() except httpx.ConnectError: - raise ValueError( + raise InvalidArgumentError( "Could not connect to a Chroma server. Are you sure it is running?" ) # Propagate ChromaErrors except ChromaError as e: raise e except Exception as e: - raise ValueError(str(e)) + raise InvalidArgumentError(str(e)) # region BaseAPI Methods # Note - we could do this in less verbose ways, but they break type checking @@ -416,21 +416,21 @@ def _validate_tenant_database(self, tenant: str, database: str) -> None: try: self._admin_client.get_tenant(name=tenant) except httpx.ConnectError: - raise ValueError( + raise InvalidArgumentError( "Could not connect to a Chroma server. Are you sure it is running?" ) # Propagate ChromaErrors except ChromaError as e: raise e except Exception: - raise ValueError( + raise InvalidArgumentError( f"Could not connect to tenant {tenant}. Are you sure it exists?" ) try: self._admin_client.get_database(name=database, tenant=tenant) except httpx.ConnectError: - raise ValueError( + raise InvalidArgumentError( "Could not connect to a Chroma server. Are you sure it is running?" ) diff --git a/chromadb/api/configuration.py b/chromadb/api/configuration.py index 03488e92909..d1b7718e803 100644 --- a/chromadb/api/configuration.py +++ b/chromadb/api/configuration.py @@ -26,7 +26,7 @@ class StaticParameterError(Exception): pass -class InvalidConfigurationError(ValueError): +class InvalidConfigurationError(InvalidArgumentError): """Represents an error that occurs when a configuration is invalid.""" pass @@ -102,23 +102,23 @@ def __init__(self, parameters: Optional[List[ConfigurationParameter]] = None): if parameters is not None: for parameter in parameters: if parameter.name not in self.definitions: - raise ValueError(f"Invalid parameter name: {parameter.name}") + raise InvalidArgumentError(f"Invalid parameter name: {parameter.name}") definition = self.definitions[parameter.name] # Handle the case where we have a recursive configuration definition if isinstance(parameter.value, dict): child_type = globals().get(parameter.value.get("_type", None)) if child_type is None: - raise ValueError( + raise InvalidArgumentError( f"Invalid configuration type: {parameter.value}" ) parameter.value = child_type.from_json(parameter.value) if not isinstance(parameter.value, type(definition.default_value)): - raise ValueError(f"Invalid parameter value: {parameter.value}") + raise InvalidArgumentError(f"Invalid parameter value: {parameter.value}") parameter_validator = definition.validator if not parameter_validator(parameter.value): - raise ValueError(f"Invalid parameter value: {parameter.value}") + raise InvalidArgumentError(f"Invalid parameter value: {parameter.value}") self.parameter_map[parameter.name] = parameter # Apply the defaults for any missing parameters for name, definition in self.definitions.items(): @@ -152,7 +152,7 @@ def get_parameters(self) -> List[ConfigurationParameter]: def get_parameter(self, name: str) -> ConfigurationParameter: """Returns the parameter with the given name, or except if it doesn't exist.""" if name not in self.parameter_map: - raise ValueError( + raise InvalidArgumentError( f"Invalid parameter name: {name} for configuration {self.__class__.__name__}" ) param_value = cast(ConfigurationParameter, self.parameter_map.get(name)) @@ -161,13 +161,13 @@ def get_parameter(self, name: str) -> ConfigurationParameter: def set_parameter(self, name: str, value: Union[str, int, float, bool]) -> None: """Sets the parameter with the given name to the given value.""" if name not in self.definitions: - raise ValueError(f"Invalid parameter name: {name}") + raise InvalidArgumentError(f"Invalid parameter name: {name}") definition = self.definitions[name] parameter = self.parameter_map[name] if definition.is_static: raise StaticParameterError(f"Cannot set static parameter: {name}") if not definition.validator(value): - raise ValueError(f"Invalid value for parameter {name}: {value}") + raise InvalidArgumentError(f"Invalid value for parameter {name}: {value}") parameter.value = value @override @@ -182,7 +182,7 @@ def from_json_str(cls, json_str: str) -> Self: try: config_json = json.loads(json_str) except json.JSONDecodeError: - raise ValueError( + raise InvalidArgumentError( f"Unable to decode configuration from JSON string: {json_str}" ) return cls.from_json(config_json) @@ -205,7 +205,7 @@ def to_json(self) -> Dict[str, Any]: def from_json(cls, json_map: Dict[str, Any]) -> Self: """Returns a configuration from the given JSON string.""" if cls.__name__ != json_map.get("_type", None): - raise ValueError( + raise InvalidArgumentError( f"Trying to instantiate configuration of type {cls.__name__} from JSON with type {json_map['_type']}" ) parameters = [] @@ -308,7 +308,7 @@ def from_legacy_params(cls, params: Dict[str, Any]) -> Self: parameters = [] for name, value in params.items(): if name not in old_to_new: - raise ValueError(f"Invalid legacy HNSW parameter name: {name}") + raise InvalidArgumentError(f"Invalid legacy HNSW parameter name: {name}") parameters.append( ConfigurationParameter(name=old_to_new[name], value=value) ) diff --git a/chromadb/api/models/AsyncCollection.py b/chromadb/api/models/AsyncCollection.py index bbae1ce46e9..4237f129c21 100644 --- a/chromadb/api/models/AsyncCollection.py +++ b/chromadb/api/models/AsyncCollection.py @@ -53,11 +53,11 @@ async def add( None Raises: - ValueError: If you don't provide either embeddings or documents - ValueError: If the length of ids, embeddings, metadatas, or documents don't match - ValueError: If you don't provide an embedding function and don't provide embeddings - ValueError: If you provide both embeddings and documents - ValueError: If you provide an id that already exists + InvalidArgumentError: If you don't provide either embeddings or documents + InvalidArgumentError: If the length of ids, embeddings, metadatas, or documents don't match + InvalidArgumentError: If you don't provide an embedding function and don't provide embeddings + InvalidArgumentError: If you provide both embeddings and documents + InvalidArgumentError: If you provide an id that already exists """ add_request = self._validate_and_prepare_add_request( @@ -194,10 +194,10 @@ async def query( QueryResult: A QueryResult object containing the results. Raises: - ValueError: If you don't provide either query_embeddings, query_texts, or query_images - ValueError: If you provide both query_embeddings and query_texts - ValueError: If you provide both query_embeddings and query_images - ValueError: If you provide both query_texts and query_images + InvalidArgumentError: If you don't provide either query_embeddings, query_texts, or query_images + InvalidArgumentError: If you provide both query_embeddings and query_texts + InvalidArgumentError: If you provide both query_embeddings and query_images + InvalidArgumentError: If you provide both query_texts and query_images """ @@ -356,7 +356,7 @@ async def delete( None Raises: - ValueError: If you don't provide either ids, where, or where_document + InvalidArgumentError: If you don't provide either ids, where, or where_document """ delete_request = self._validate_and_prepare_delete_request( ids, where, where_document diff --git a/chromadb/api/models/Collection.py b/chromadb/api/models/Collection.py index e477818ccd6..3c02fa419a0 100644 --- a/chromadb/api/models/Collection.py +++ b/chromadb/api/models/Collection.py @@ -71,11 +71,11 @@ def add( None Raises: - ValueError: If you don't provide either embeddings or documents - ValueError: If the length of ids, embeddings, metadatas, or documents don't match - ValueError: If you don't provide an embedding function and don't provide embeddings - ValueError: If you provide both embeddings and documents - ValueError: If you provide an id that already exists + InvalidArgumentError: If you don't provide either embeddings or documents + InvalidArgumentError: If the length of ids, embeddings, metadatas, or documents don't match + InvalidArgumentError: If you don't provide an embedding function and don't provide embeddings + InvalidArgumentError: If you provide both embeddings and documents + InvalidArgumentError: If you provide an id that already exists """ @@ -201,10 +201,10 @@ def query( QueryResult: A QueryResult object containing the results. Raises: - ValueError: If you don't provide either query_embeddings, query_texts, or query_images - ValueError: If you provide both query_embeddings and query_texts - ValueError: If you provide both query_embeddings and query_images - ValueError: If you provide both query_texts and query_images + InvalidArgumentError: If you don't provide either query_embeddings, query_texts, or query_images + InvalidArgumentError: If you provide both query_embeddings and query_texts + InvalidArgumentError: If you provide both query_embeddings and query_images + InvalidArgumentError: If you provide both query_texts and query_images """ @@ -369,7 +369,7 @@ def delete( None Raises: - ValueError: If you don't provide either ids, where, or where_document + InvalidArgumentError: If you don't provide either ids, where, or where_document """ delete_request = self._validate_and_prepare_delete_request( ids, where, where_document diff --git a/chromadb/api/models/CollectionCommon.py b/chromadb/api/models/CollectionCommon.py index d2b3cd3789e..2fefa49773a 100644 --- a/chromadb/api/models/CollectionCommon.py +++ b/chromadb/api/models/CollectionCommon.py @@ -242,7 +242,7 @@ def _validate_and_prepare_get_request( validate_include(include=include, dissalowed=[IncludeEnum.distances]) if IncludeEnum.data in include and self._data_loader is None: - raise ValueError( + raise InvalidArgumentError( "You must set a data loader on the collection if loading from URIs." ) @@ -423,7 +423,7 @@ def _validate_and_prepare_delete_request( where_document: Optional[WhereDocument], ) -> DeleteRequest: if ids is None and where is None and where_document is None: - raise ValueError( + raise InvalidArgumentError( "At least one of ids, where, or where_document must be provided" ) @@ -493,7 +493,7 @@ def _validate_modify_request(self, metadata: Optional[CollectionMetadata]) -> No if metadata is not None: validate_metadata(metadata) if "hnsw:space" in metadata: - raise ValueError( + raise InvalidArgumentError( "Changing the distance function of a collection once it is created is not supported currently." ) @@ -516,7 +516,7 @@ def _embed_record_set( # uris require special handling if field == "uris": if self._data_loader is None: - raise ValueError( + raise InvalidArgumentError( "You must set a data loader on the collection if loading from URIs." ) return self._embed( @@ -524,7 +524,7 @@ def _embed_record_set( ) else: return self._embed(input=record_set[field]) # type: ignore[literal-required] - raise ValueError( + raise InvalidArgumentError( "Record does not contain any non-None fields that can be embedded." f"Embeddable Fields: {embeddable_fields}" f"Record Fields: {record_set}" @@ -532,7 +532,7 @@ def _embed_record_set( def _embed(self, input: Any) -> Embeddings: if self._embedding_function is None: - raise ValueError( + raise InvalidArgumentError( "You must provide an embedding function to compute embeddings." "https://docs.trychroma.com/guides/embeddings" ) diff --git a/chromadb/api/segment.py b/chromadb/api/segment.py index b25d6550182..ea4add6e031 100644 --- a/chromadb/api/segment.py +++ b/chromadb/api/segment.py @@ -87,13 +87,13 @@ def check_index_name(index_name: str) -> None: f"got {index_name}" ) if len(index_name) < 3 or len(index_name) > 63: - raise ValueError(msg) + raise InvalidArgumentError(msg) if not re.match("^[a-zA-Z0-9][a-zA-Z0-9._-]*[a-zA-Z0-9]$", index_name): - raise ValueError(msg) + raise InvalidArgumentError(msg) if ".." in index_name: - raise ValueError(msg) + raise InvalidArgumentError(msg) if re.match("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$", index_name): - raise ValueError(msg) + raise InvalidArgumentError(msg) def rate_limit(func: T) -> T: @@ -138,7 +138,7 @@ def heartbeat(self) -> int: @override def create_database(self, name: str, tenant: str = DEFAULT_TENANT) -> None: if len(name) < 3: - raise ValueError("Database name must be at least 3 characters long") + raise InvalidArgumentError("Database name must be at least 3 characters long") self._quota_enforcer.enforce( action=Action.CREATE_DATABASE, @@ -161,7 +161,7 @@ def get_database(self, name: str, tenant: str = DEFAULT_TENANT) -> t.Database: @override def create_tenant(self, name: str) -> None: if len(name) < 3: - raise ValueError("Tenant name must be at least 3 characters long") + raise InvalidArgumentError("Tenant name must be at least 3 characters long") self._sysdb.create_tenant( name=name, @@ -389,7 +389,7 @@ def delete_collection( ) self._manager.delete_segments(existing[0].id) else: - raise ValueError(f"Collection {name} does not exist.") + raise InvalidArgumentError(f"Collection {name} does not exist.") @trace_method("SegmentAPI._add", OpenTelemetryGranularity.OPERATION) @override @@ -667,7 +667,7 @@ def _delete( or (where_document is not None and len(where_document) == 0) ) ): - raise ValueError( + raise InvalidArgumentError( """ You must provide either ids, where, or where_document to delete. If you want to delete all data in a collection you can delete the diff --git a/chromadb/api/shared_system_client.py b/chromadb/api/shared_system_client.py index 9e2f7f90052..e627d659194 100644 --- a/chromadb/api/shared_system_client.py +++ b/chromadb/api/shared_system_client.py @@ -35,7 +35,7 @@ def _create_system_if_not_exists( # For now, the settings must match if previous_system.settings != settings: - raise ValueError( + raise InvalidArgumentError( f"An instance of Chroma already exists for {identifier} with different settings" ) @@ -47,7 +47,7 @@ def _get_identifier_from_settings(settings: Settings) -> str: api_impl = settings.chroma_api_impl if api_impl is None: - raise ValueError("Chroma API implementation must be set in settings") + raise InvalidArgumentError("Chroma API implementation must be set in settings") elif api_impl == "chromadb.api.segment.SegmentAPI": if settings.is_persistent: identifier = settings.persist_directory @@ -62,7 +62,7 @@ def _get_identifier_from_settings(settings: Settings) -> str: # FastAPI clients can all use unique system identifiers since their configurations can be independent, e.g. different auth tokens identifier = str(uuid.uuid4()) else: - raise ValueError(f"Unsupported Chroma API implementation {api_impl}") + raise InvalidArgumentError(f"Unsupported Chroma API implementation {api_impl}") return identifier diff --git a/chromadb/api/types.py b/chromadb/api/types.py index 717e2d605a8..4183b2b94b7 100644 --- a/chromadb/api/types.py +++ b/chromadb/api/types.py @@ -58,7 +58,7 @@ def normalize_embeddings( return None if len(target) == 0: - raise ValueError( + raise InvalidArgumentError( f"Expected Embedings to be non-empty list or numpy array, got {target}" ) @@ -85,7 +85,7 @@ def normalize_embeddings( if target.ndim == 2: return list(target) - raise ValueError( + raise InvalidArgumentError( f"Expected embeddings to be a list of floats or ints, a list of lists, a numpy array, or a list of numpy arrays, got {target}" ) @@ -234,7 +234,7 @@ def _validate_record_set_length_consistency(record_set: BaseRecordSet) -> None: lengths = [len(lst) for lst in record_set.values() if lst is not None] # type: ignore[arg-type] if not lengths: - raise ValueError( + raise InvalidArgumentError( f"At least one of one of {', '.join(record_set.keys())} must be provided" ) @@ -243,13 +243,13 @@ def _validate_record_set_length_consistency(record_set: BaseRecordSet) -> None: ] if zero_lengths: - raise ValueError(f"Non-empty lists are required for {zero_lengths}") + raise InvalidArgumentError(f"Non-empty lists are required for {zero_lengths}") if len(set(lengths)) > 1: error_str = ", ".join( f"{key}: {len(lst)}" for key, lst in record_set.items() if lst is not None # type: ignore[arg-type] ) - raise ValueError(f"Unequal lengths for fields: {error_str}") + raise InvalidArgumentError(f"Unequal lengths for fields: {error_str}") def validate_record_set_for_embedding( @@ -259,7 +259,7 @@ def validate_record_set_for_embedding( Validates that the Record is ready to be embedded, i.e. that it contains exactly one of the embeddable fields. """ if record_set["embeddings"] is not None: - raise ValueError("Attempting to embed a record that already has embeddings.") + raise InvalidArgumentError("Attempting to embed a record that already has embeddings.") if embeddable_fields is None: embeddable_fields = get_default_embeddable_record_set_fields() validate_record_set_contains_one(record_set, embeddable_fields) @@ -274,7 +274,7 @@ def validate_record_set_contains_any( _validate_record_set_contains(record_set, contains_any) if not any(record_set[field] is not None for field in contains_any): # type: ignore[literal-required] - raise ValueError(f"At least one of {', '.join(contains_any)} must be provided") + raise InvalidArgumentError(f"At least one of {', '.join(contains_any)} must be provided") def validate_record_set_contains_one( @@ -285,7 +285,7 @@ def validate_record_set_contains_one( """ _validate_record_set_contains(record_set, contains_one) if sum(record_set[field] is not None for field in contains_one) != 1: # type: ignore[literal-required] - raise ValueError(f"Exactly one of {', '.join(contains_one)} must be provided") + raise InvalidArgumentError(f"Exactly one of {', '.join(contains_one)} must be provided") def _validate_record_set_contains( @@ -295,7 +295,7 @@ def _validate_record_set_contains( Validates that all fields in contains are valid fields of the Record. """ if any(field not in record_set for field in contains): - raise ValueError( + raise InvalidArgumentError( f"Invalid field in contains: {', '.join(contains)}, available fields: {', '.join(record_set.keys())}" ) @@ -484,7 +484,7 @@ def validate_embedding_function( protocol_signature = signature(EmbeddingFunction.__call__).parameters.keys() if not function_signature == protocol_signature: - raise ValueError( + raise InvalidArgumentError( f"Expected EmbeddingFunction.__call__ to have the following signature: {protocol_signature}, got {function_signature}\n" "Please see https://docs.trychroma.com/guides/embeddings for details of the EmbeddingFunction interface.\n" "Please note the recent change to the EmbeddingFunction interface: https://docs.trychroma.com/deployment/migration#migration-to-0.4.16---november-7,-2023 \n" @@ -499,14 +499,14 @@ def __call__(self, uris: URIs) -> L: def validate_ids(ids: IDs) -> IDs: """Validates ids to ensure it is a list of strings""" if not isinstance(ids, list): - raise ValueError(f"Expected IDs to be a list, got {type(ids).__name__} as IDs") + raise InvalidArgumentError(f"Expected IDs to be a list, got {type(ids).__name__} as IDs") if len(ids) == 0: - raise ValueError(f"Expected IDs to be a non-empty list, got {len(ids)} IDs") + raise InvalidArgumentError(f"Expected IDs to be a non-empty list, got {len(ids)} IDs") seen = set() dups = set() for id_ in ids: if not isinstance(id_, str): - raise ValueError(f"Expected ID to be a str, got {id_}") + raise InvalidArgumentError(f"Expected ID to be a str, got {id_}") if id_ in seen: dups.add(id_) else: @@ -535,27 +535,27 @@ def validate_ids(ids: IDs) -> IDs: def validate_metadata(metadata: Metadata) -> Metadata: """Validates metadata to ensure it is a dictionary of strings to strings, ints, floats or bools""" if not isinstance(metadata, dict) and metadata is not None: - raise ValueError( + raise InvalidArgumentError( f"Expected metadata to be a dict or None, got {type(metadata).__name__} as metadata" ) if metadata is None: return metadata if len(metadata) == 0: - raise ValueError( + raise InvalidArgumentError( f"Expected metadata to be a non-empty dict, got {len(metadata)} metadata attributes" ) for key, value in metadata.items(): if key == META_KEY_CHROMA_DOCUMENT: - raise ValueError( + raise InvalidArgumentError( f"Expected metadata to not contain the reserved key {META_KEY_CHROMA_DOCUMENT}" ) if not isinstance(key, str): - raise TypeError( + raise InvalidArgumentError( f"Expected metadata key to be a str, got {key} which is a {type(key).__name__}" ) # isinstance(True, int) evaluates to True, so we need to check for bools separately if not isinstance(value, bool) and not isinstance(value, (str, int, float)): - raise ValueError( + raise InvalidArgumentError( f"Expected metadata value to be a str, int, float or bool, got {value} which is a {type(value).__name__}" ) return metadata @@ -564,21 +564,21 @@ def validate_metadata(metadata: Metadata) -> Metadata: def validate_update_metadata(metadata: UpdateMetadata) -> UpdateMetadata: """Validates metadata to ensure it is a dictionary of strings to strings, ints, floats or bools""" if not isinstance(metadata, dict) and metadata is not None: - raise ValueError( + raise InvalidArgumentError( f"Expected metadata to be a dict or None, got {type(metadata)}" ) if metadata is None: return metadata if len(metadata) == 0: - raise ValueError(f"Expected metadata to be a non-empty dict, got {metadata}") + raise InvalidArgumentError(f"Expected metadata to be a non-empty dict, got {metadata}") for key, value in metadata.items(): if not isinstance(key, str): - raise ValueError(f"Expected metadata key to be a str, got {key}") + raise InvalidArgumentError(f"Expected metadata key to be a str, got {key}") # isinstance(True, int) evaluates to True, so we need to check for bools separately if not isinstance(value, bool) and not isinstance( value, (str, int, float, type(None)) ): - raise ValueError( + raise InvalidArgumentError( f"Expected metadata value to be a str, int, or float, got {value}" ) return metadata @@ -587,7 +587,7 @@ def validate_update_metadata(metadata: UpdateMetadata) -> UpdateMetadata: def validate_metadatas(metadatas: Metadatas) -> Metadatas: """Validates metadatas to ensure it is a list of dictionaries of strings to strings, ints, floats or bools""" if not isinstance(metadatas, list): - raise ValueError(f"Expected metadatas to be a list, got {metadatas}") + raise InvalidArgumentError(f"Expected metadatas to be a list, got {metadatas}") for metadata in metadatas: validate_metadata(metadata) return metadatas @@ -599,12 +599,12 @@ def validate_where(where: Where) -> None: or in the case of $and and $or, a list of where expressions """ if not isinstance(where, dict): - raise ValueError(f"Expected where to be a dict, got {where}") + raise InvalidArgumentError(f"Expected where to be a dict, got {where}") if len(where) != 1: - raise ValueError(f"Expected where to have exactly one operator, got {where}") + raise InvalidArgumentError(f"Expected where to have exactly one operator, got {where}") for key, value in where.items(): if not isinstance(key, str): - raise ValueError(f"Expected where key to be a str, got {key}") + raise InvalidArgumentError(f"Expected where key to be a str, got {key}") if ( key != "$and" and key != "$or" @@ -612,16 +612,16 @@ def validate_where(where: Where) -> None: and key != "$nin" and not isinstance(value, (str, int, float, dict)) ): - raise ValueError( + raise InvalidArgumentError( f"Expected where value to be a str, int, float, or operator expression, got {value}" ) if key == "$and" or key == "$or": if not isinstance(value, list): - raise ValueError( + raise InvalidArgumentError( f"Expected where value for $and or $or to be a list of where expressions, got {value}" ) if len(value) <= 1: - raise ValueError( + raise InvalidArgumentError( f"Expected where value for $and or $or to be a list with at least two where expressions, got {value}" ) for where_expression in value: @@ -630,7 +630,7 @@ def validate_where(where: Where) -> None: if isinstance(value, dict): # Ensure there is only one operator if len(value) != 1: - raise ValueError( + raise InvalidArgumentError( f"Expected operator expression to have exactly one operator, got {value}" ) @@ -638,12 +638,12 @@ def validate_where(where: Where) -> None: # Only numbers can be compared with gt, gte, lt, lte if operator in ["$gt", "$gte", "$lt", "$lte"]: if not isinstance(operand, (int, float)): - raise ValueError( + raise InvalidArgumentError( f"Expected operand value to be an int or a float for operator {operator}, got {operand}" ) if operator in ["$in", "$nin"]: if not isinstance(operand, list): - raise ValueError( + raise InvalidArgumentError( f"Expected operand value to be an list for operator {operator}, got {operand}" ) if operator not in [ @@ -656,20 +656,20 @@ def validate_where(where: Where) -> None: "$in", "$nin", ]: - raise ValueError( + raise InvalidArgumentError( f"Expected where operator to be one of $gt, $gte, $lt, $lte, $ne, $eq, $in, $nin, " f"got {operator}" ) if not isinstance(operand, (str, int, float, list)): - raise ValueError( + raise InvalidArgumentError( f"Expected where operand value to be a str, int, float, or list of those type, got {operand}" ) if isinstance(operand, list) and ( len(operand) == 0 or not all(isinstance(x, type(operand[0])) for x in operand) ): - raise ValueError( + raise InvalidArgumentError( f"Expected where operand value to be a non-empty list, and all values to be of the same type " f"got {operand}" ) @@ -681,36 +681,36 @@ def validate_where_document(where_document: WhereDocument) -> None: a list of where_document expressions """ if not isinstance(where_document, dict): - raise ValueError( + raise InvalidArgumentError( f"Expected where document to be a dictionary, got {where_document}" ) if len(where_document) != 1: - raise ValueError( + raise InvalidArgumentError( f"Expected where document to have exactly one operator, got {where_document}" ) for operator, operand in where_document.items(): if operator not in ["$contains", "$not_contains", "$and", "$or"]: - raise ValueError( + raise InvalidArgumentError( f"Expected where document operator to be one of $contains, $and, $or, got {operator}" ) if operator == "$and" or operator == "$or": if not isinstance(operand, list): - raise ValueError( + raise InvalidArgumentError( f"Expected document value for $and or $or to be a list of where document expressions, got {operand}" ) if len(operand) <= 1: - raise ValueError( + raise InvalidArgumentError( f"Expected document value for $and or $or to be a list with at least two where document expressions, got {operand}" ) for where_document_expression in operand: validate_where_document(where_document_expression) # Value is a $contains operator elif not isinstance(operand, str): - raise ValueError( + raise InvalidArgumentError( f"Expected where document operand value for operator $contains to be a str, got {operand}" ) elif len(operand) == 0: - raise ValueError( + raise InvalidArgumentError( "Expected where document operand value for operator $contains to be a non-empty str" ) @@ -720,18 +720,18 @@ def validate_include(include: Include, dissalowed: Optional[Include] = None) -> to control if distances is allowed""" if not isinstance(include, list): - raise ValueError(f"Expected include to be a list, got {include}") + raise InvalidArgumentError(f"Expected include to be a list, got {include}") for item in include: if not isinstance(item, str): - raise ValueError(f"Expected include item to be a str, got {item}") + raise InvalidArgumentError(f"Expected include item to be a str, got {item}") if not any(item == e for e in IncludeEnum): - raise ValueError( + raise InvalidArgumentError( f"Expected include item to be one of {', '.join(IncludeEnum)}, got {item}" ) if dissalowed is not None and any(item == e for e in dissalowed): - raise ValueError( + raise InvalidArgumentError( f"Include item cannot be one of {', '.join(dissalowed)}, got {item}" ) @@ -740,11 +740,11 @@ def validate_n_results(n_results: int) -> int: """Validates n_results to ensure it is a positive Integer. Since hnswlib does not allow n_results to be negative.""" # Check Number of requested results if not isinstance(n_results, int): - raise ValueError( + raise InvalidArgumentError( f"Expected requested number of results to be a int, got {n_results}" ) if n_results <= 0: - raise TypeError( + raise InvalidArgumentError( f"Number of requested results {n_results}, cannot be negative, or zero." ) return n_results @@ -753,25 +753,25 @@ def validate_n_results(n_results: int) -> int: def validate_embeddings(embeddings: Embeddings) -> Embeddings: """Validates embeddings to ensure it is a list of numpy arrays of ints, or floats""" if not isinstance(embeddings, (list, np.ndarray)): - raise ValueError( + raise InvalidArgumentError( f"Expected embeddings to be a list, got {type(embeddings).__name__}" ) if len(embeddings) == 0: - raise ValueError( + raise InvalidArgumentError( f"Expected embeddings to be a list with at least one item, got {len(embeddings)} embeddings" ) if not all([isinstance(e, np.ndarray) for e in embeddings]): - raise ValueError( + raise InvalidArgumentError( "Expected each embedding in the embeddings to be a numpy array, got " f"{list(set([type(e).__name__ for e in embeddings]))}" ) for i, embedding in enumerate(embeddings): if embedding.ndim == 0: - raise ValueError( + raise InvalidArgumentError( f"Expected a 1-dimensional array, got a 0-dimensional array {embedding}" ) if embedding.size == 0: - raise ValueError( + raise InvalidArgumentError( f"Expected each embedding in the embeddings to be a 1-dimensional numpy array with at least 1 int/float value. Got a 1-dimensional numpy array with no values at pos {i}" ) if not all( @@ -781,7 +781,7 @@ def validate_embeddings(embeddings: Embeddings) -> Embeddings: for value in embedding ] ): - raise ValueError( + raise InvalidArgumentError( "Expected each value in the embedding to be a int or float, got an embedding with " f"{list(set([type(value).__name__ for value in embedding]))} - {embedding}" ) @@ -791,11 +791,11 @@ def validate_embeddings(embeddings: Embeddings) -> Embeddings: def validate_documents(documents: Documents, nullable: bool = False) -> None: """Validates documents to ensure it is a list of strings""" if not isinstance(documents, list): - raise ValueError( + raise InvalidArgumentError( f"Expected documents to be a list, got {type(documents).__name__}" ) if len(documents) == 0: - raise ValueError( + raise InvalidArgumentError( f"Expected documents to be a non-empty list, got {len(documents)} documents" ) for document in documents: @@ -803,20 +803,20 @@ def validate_documents(documents: Documents, nullable: bool = False) -> None: if document is None and nullable: continue if not is_document(document): - raise ValueError(f"Expected document to be a str, got {document}") + raise InvalidArgumentError(f"Expected document to be a str, got {document}") def validate_images(images: Images) -> None: """Validates images to ensure it is a list of numpy arrays""" if not isinstance(images, list): - raise ValueError(f"Expected images to be a list, got {type(images).__name__}") + raise InvalidArgumentError(f"Expected images to be a list, got {type(images).__name__}") if len(images) == 0: - raise ValueError( + raise InvalidArgumentError( f"Expected images to be a non-empty list, got {len(images)} images" ) for image in images: if not is_image(image): - raise ValueError(f"Expected image to be a numpy array, got {image}") + raise InvalidArgumentError(f"Expected image to be a numpy array, got {image}") def validate_batch( @@ -830,7 +830,7 @@ def validate_batch( limits: Dict[str, Any], ) -> None: if len(batch[0]) > limits["max_batch_size"]: - raise ValueError( + raise InvalidArgumentError( f"Batch size {len(batch[0])} exceeds maximum batch size {limits['max_batch_size']}" ) diff --git a/chromadb/auth/__init__.py b/chromadb/auth/__init__.py index ad0f7e3c99f..56c0316dd1f 100644 --- a/chromadb/auth/__init__.py +++ b/chromadb/auth/__init__.py @@ -109,12 +109,12 @@ def read_creds_or_creds_file(self) -> List[str]: if self._system.settings.chroma_server_authn_credentials: _creds = str(self._system.settings["chroma_server_authn_credentials"]) if not _creds_file and not _creds: - raise ValueError( + raise InvalidArgumentError( "No credentials file or credentials found in " "[chroma_server_authn_credentials]." ) if _creds_file and _creds: - raise ValueError( + raise InvalidArgumentError( "Both credentials file and credentials found." "Please provide only one." ) @@ -123,7 +123,7 @@ def read_creds_or_creds_file(self) -> List[str]: elif _creds_file: with open(_creds_file, "r") as f: return f.readlines() - raise ValueError("Should never happen") + raise InvalidArgumentError("Should never happen") def singleton_tenant_database_if_applicable( self, user: Optional[UserIdentity] @@ -219,11 +219,11 @@ def read_config_or_config_file(self) -> List[str]: if self._system.settings.chroma_server_authz_config: _config = str(self._system.settings["chroma_server_authz_config"]) if not _config_file and not _config: - raise ValueError( + raise InvalidArgumentError( "No authz configuration file or authz configuration found." ) if _config_file and _config: - raise ValueError( + raise InvalidArgumentError( "Both authz configuration file and authz configuration found." "Please provide only one." ) @@ -232,4 +232,4 @@ def read_config_or_config_file(self) -> List[str]: elif _config_file: with open(_config_file, "r") as f: return f.readlines() - raise ValueError("Should never happen") + raise InvalidArgumentError("Should never happen") diff --git a/chromadb/auth/basic_authn/__init__.py b/chromadb/auth/basic_authn/__init__.py index 66af698513b..02c27945675 100644 --- a/chromadb/auth/basic_authn/__init__.py +++ b/chromadb/auth/basic_authn/__init__.py @@ -84,14 +84,14 @@ def __init__(self, system: System) -> None: and len(_raw_creds) != 2 or not all(_raw_creds) ): - raise ValueError( + raise InvalidArgumentError( f"Invalid htpasswd credentials found: {_raw_creds}. " "Lines must be exactly :." ) username = _raw_creds[0] password = _raw_creds[1] if username in self._creds: - raise ValueError( + raise InvalidArgumentError( "Duplicate username found in " "[chroma_server_authn_credentials]. " "Usernames must be unique." diff --git a/chromadb/auth/token_authn/__init__.py b/chromadb/auth/token_authn/__init__.py index 00c6ae3a449..b7d5c494d35 100644 --- a/chromadb/auth/token_authn/__init__.py +++ b/chromadb/auth/token_authn/__init__.py @@ -56,7 +56,7 @@ class TokenTransportHeader(str, Enum): def _check_token(token: str) -> None: token_str = str(token) if not all(c in valid_token_chars for c in token_str): - raise ValueError( + raise InvalidArgumentError( "Invalid token. Must contain only ASCII letters, digits, and punctuation." ) @@ -69,7 +69,7 @@ def _check_token(token: str) -> None: def _check_allowed_token_headers(token_header: str) -> None: if token_header not in allowed_token_headers: - raise ValueError( + raise InvalidArgumentError( f"Invalid token transport header: {token_header}. " f"Must be one of {allowed_token_headers}" ) @@ -169,7 +169,7 @@ def __init__(self, system: System) -> None: self._users = cast(List[User], yaml.safe_load("\n".join(creds))["users"]) for user in self._users: if "tokens" not in user: - raise ValueError("User missing tokens") + raise InvalidArgumentError("User missing tokens") if "tenant" not in user: user["tenant"] = "*" if "databases" not in user: @@ -180,7 +180,7 @@ def __init__(self, system: System) -> None: token in self._token_user_mapping and self._token_user_mapping[token] != user ): - raise ValueError( + raise InvalidArgumentError( f"Token {token} already in use: wanted to use it for " f"user {user['id']} but it's already in use by " f"user {self._token_user_mapping[token]}" diff --git a/chromadb/config.py b/chromadb/config.py index acb63b98b96..0933077d5d5 100644 --- a/chromadb/config.py +++ b/chromadb/config.py @@ -282,14 +282,14 @@ def require(self, key: str) -> Any: set""" val = self[key] if val is None: - raise ValueError(f"Missing required config value '{key}'") + raise InvalidArgumentError(f"Missing required config value '{key}'") return val def __getitem__(self, key: str) -> Any: val = getattr(self, key) # Error on legacy config values if isinstance(val, str) and val in _legacy_config_values: - raise ValueError(LEGACY_ERROR) + raise InvalidArgumentError(LEGACY_ERROR) return val class Config: @@ -356,7 +356,7 @@ def __init__(self, settings: Settings): # Validate settings don't contain any legacy config values for key in _legacy_config_keys: if settings[key] is not None: - raise ValueError(LEGACY_ERROR) + raise InvalidArgumentError(LEGACY_ERROR) if ( settings["chroma_segment_cache_policy"] is not None @@ -414,7 +414,7 @@ def instance(self, type: Type[T]) -> T: if inspect.isabstract(type): type_fqn = get_fqn(type) if type_fqn not in _abstract_type_keys: - raise ValueError(f"Cannot instantiate abstract type: {type}") + raise InvalidArgumentError(f"Cannot instantiate abstract type: {type}") key = _abstract_type_keys[type_fqn] fqn = self.settings.require(key) type = get_class(fqn, type) @@ -453,7 +453,7 @@ def stop(self) -> None: def reset_state(self) -> None: """Reset the state of this system and all constituents in reverse dependency order""" if not self.settings.allow_reset: - raise ValueError( + raise InvalidArgumentError( "Resetting is not allowed by this configuration (to enable it, set `allow_reset` to `True` in your Settings() or include `ALLOW_RESET=TRUE` in your environment variables)" ) for component in reversed(list(self.components())): diff --git a/chromadb/db/base.py b/chromadb/db/base.py index 0abe62208e9..f6049a85a57 100644 --- a/chromadb/db/base.py +++ b/chromadb/db/base.py @@ -117,7 +117,7 @@ def decode_seq_id(seq_id_bytes: Union[bytes, int]) -> SeqId: elif len(seq_id_bytes) == 24: return int.from_bytes(seq_id_bytes, "big") else: - raise ValueError(f"Unknown SeqID type with length {len(seq_id_bytes)}") + raise InvalidArgumentError(f"Unknown SeqID type with length {len(seq_id_bytes)}") @staticmethod def encode_seq_id(seq_id: SeqId) -> bytes: @@ -127,7 +127,7 @@ def encode_seq_id(seq_id: SeqId) -> bytes: elif seq_id.bit_length() <= 192: return int.to_bytes(seq_id, 24, "big") else: - raise ValueError(f"Unsupported SeqID: {seq_id}") + raise InvalidArgumentError(f"Unsupported SeqID: {seq_id}") _context = local() diff --git a/chromadb/db/impl/grpc/client.py b/chromadb/db/impl/grpc/client.py index ea89ef24424..c04c8ae1b8f 100644 --- a/chromadb/db/impl/grpc/client.py +++ b/chromadb/db/impl/grpc/client.py @@ -336,7 +336,7 @@ def get_collections( ) if name is not None: if tenant is None and database is None: - raise ValueError( + raise InvalidArgumentError( "If name is specified, tenant and database must also be specified in order to uniquely identify the collection" ) request = GetCollectionsRequest( diff --git a/chromadb/db/impl/sqlite.py b/chromadb/db/impl/sqlite.py index 24087f8669e..d2bf3f22f55 100644 --- a/chromadb/db/impl/sqlite.py +++ b/chromadb/db/impl/sqlite.py @@ -147,7 +147,7 @@ def tx(self) -> TxWrapper: @override def reset_state(self) -> None: if not self._settings.require("allow_reset"): - raise ValueError( + raise InvalidArgumentError( "Resetting the database is not allowed. Set `allow_reset` to true in the config in tests or other non-production environments where reset should be permitted." ) with self.tx() as cur: diff --git a/chromadb/db/mixins/embeddings_queue.py b/chromadb/db/mixins/embeddings_queue.py index d072c852e1a..e20453f8d52 100644 --- a/chromadb/db/mixins/embeddings_queue.py +++ b/chromadb/db/mixins/embeddings_queue.py @@ -408,9 +408,9 @@ def _validate_range( start = start or self._next_seq_id() end = end or self.max_seqid() if not isinstance(start, int) or not isinstance(end, int): - raise TypeError("SeqIDs must be integers for sql-based EmbeddingsDB") + raise InvalidArgumentError("SeqIDs must be integers for sql-based EmbeddingsDB") if start >= end: - raise ValueError(f"Invalid SeqID range: {start} to {end}") + raise InvalidArgumentError(f"Invalid SeqID range: {start} to {end}") return start, end @trace_method("SqlEmbeddingsQueue._next_seq_id", OpenTelemetryGranularity.ALL) diff --git a/chromadb/db/mixins/sysdb.py b/chromadb/db/mixins/sysdb.py index 8c7f2b843ee..c89f56563f8 100644 --- a/chromadb/db/mixins/sysdb.py +++ b/chromadb/db/mixins/sysdb.py @@ -219,7 +219,7 @@ def create_collection( database: str = DEFAULT_DATABASE, ) -> Tuple[Collection, bool]: if id is None and not get_or_create: - raise ValueError("id must be specified if get_or_create is False") + raise InvalidArgumentError("id must be specified if get_or_create is False") add_attributes_to_current_span( { @@ -388,7 +388,7 @@ def get_collections( """Get collections by name, embedding function and/or metadata""" if name is not None and (tenant is None or database is None): - raise ValueError( + raise InvalidArgumentError( "If name is specified, tenant and database must also be specified in order to uniquely identify the collection" ) @@ -813,7 +813,7 @@ def _load_config_from_json_str_and_migrate( try: config_json = json.loads(json_str) except json.JSONDecodeError: - raise ValueError( + raise InvalidArgumentError( f"Unable to decode configuration from JSON string: {json_str}" ) diff --git a/chromadb/ingest/__init__.py b/chromadb/ingest/__init__.py index f40ba2f50c9..a7a546b62e2 100644 --- a/chromadb/ingest/__init__.py +++ b/chromadb/ingest/__init__.py @@ -20,7 +20,7 @@ def encode_vector(vector: Vector, encoding: ScalarEncoding) -> bytes: elif encoding == ScalarEncoding.INT32: return np.array(vector, dtype=np.int32).tobytes() else: - raise ValueError(f"Unsupported encoding: {encoding.value}") + raise InvalidArgumentError(f"Unsupported encoding: {encoding.value}") def decode_vector(vector: bytes, encoding: ScalarEncoding) -> Vector: @@ -31,7 +31,7 @@ def decode_vector(vector: bytes, encoding: ScalarEncoding) -> Vector: elif encoding == ScalarEncoding.INT32: return np.frombuffer(vector, dtype=np.float32) else: - raise ValueError(f"Unsupported encoding: {encoding.value}") + raise InvalidArgumentError(f"Unsupported encoding: {encoding.value}") class Producer(Component): diff --git a/chromadb/ingest/impl/utils.py b/chromadb/ingest/impl/utils.py index 4ad92df6bc3..82d1283c700 100644 --- a/chromadb/ingest/impl/utils.py +++ b/chromadb/ingest/impl/utils.py @@ -12,7 +12,7 @@ def parse_topic_name(topic_name: str) -> Tuple[str, str, str]: """Parse the topic name into the tenant, namespace and topic name""" match = re.match(topic_regex, topic_name) if not match: - raise ValueError(f"Invalid topic name: {topic_name}") + raise InvalidArgumentError(f"Invalid topic name: {topic_name}") return match.group("tenant"), match.group("namespace"), match.group("topic") diff --git a/chromadb/proto/convert.py b/chromadb/proto/convert.py index 51d30bc608a..e8bcbc3fbe6 100644 --- a/chromadb/proto/convert.py +++ b/chromadb/proto/convert.py @@ -55,7 +55,7 @@ def to_proto_vector(vector: Vector, encoding: ScalarEncoding) -> chroma_pb.Vecto as_bytes = np.array(vector, dtype=np.int32).tobytes() proto_encoding = chroma_pb.ScalarEncoding.INT32 else: - raise ValueError( + raise InvalidArgumentError( f"Unknown encoding {encoding}, expected one of {ScalarEncoding.FLOAT32} \ or {ScalarEncoding.INT32}" ) @@ -73,7 +73,7 @@ def from_proto_vector(vector: chroma_pb.Vector) -> Tuple[Embedding, ScalarEncodi as_array = np.frombuffer(vector.vector, dtype=np.int32) out_encoding = ScalarEncoding.INT32 else: - raise ValueError( + raise InvalidArgumentError( f"Unknown encoding {encoding}, expected one of \ {chroma_pb.ScalarEncoding.FLOAT32} or {chroma_pb.ScalarEncoding.INT32}" ) @@ -125,7 +125,7 @@ def _from_proto_metadata_handle_none( elif is_update: out_metadata[key] = None else: - raise ValueError(f"Metadata key {key} value cannot be None") + raise InvalidArgumentError(f"Metadata key {key} value cannot be None") return out_metadata @@ -218,7 +218,7 @@ def to_proto_metadata_update_value( elif value is None: return chroma_pb.UpdateMetadataValue() else: - raise ValueError( + raise InvalidArgumentError( f"Unknown metadata value type {type(value)}, expected one of str, int, \ float, or None" ) @@ -270,7 +270,7 @@ def to_proto_operation(operation: Operation) -> chroma_pb.Operation: elif operation == Operation.DELETE: return chroma_pb.Operation.DELETE else: - raise ValueError( + raise InvalidArgumentError( f"Unknown operation {operation}, expected one of {Operation.ADD}, \ {Operation.UPDATE}, {Operation.UPDATE}, or {Operation.DELETE}" ) @@ -345,15 +345,15 @@ def to_proto_request_version_context( def to_proto_where(where: Where) -> chroma_pb.Where: response = chroma_pb.Where() if len(where) != 1: - raise ValueError(f"Expected where to have exactly one operator, got {where}") + raise InvalidArgumentError(f"Expected where to have exactly one operator, got {where}") for key, value in where.items(): if not isinstance(key, str): - raise ValueError(f"Expected where key to be a str, got {key}") + raise InvalidArgumentError(f"Expected where key to be a str, got {key}") if key == "$and" or key == "$or": if not isinstance(value, list): - raise ValueError( + raise InvalidArgumentError( f"Expected where value for $and or $or to be a list of where expressions, got {value}" ) children: chroma_pb.WhereChildren = chroma_pb.WhereChildren( @@ -396,20 +396,20 @@ def to_proto_where(where: Where) -> chroma_pb.Where: sdc.generic_comparator = chroma_pb.GenericComparator.EQ dc.single_double_operand.CopyFrom(sdc) else: - raise ValueError( + raise InvalidArgumentError( f"Expected where value to be a string, int, or float, got {value}" ) else: for operator, operand in value.items(): if operator in ["$in", "$nin"]: if not isinstance(operand, list): - raise ValueError( + raise InvalidArgumentError( f"Expected where value for $in or $nin to be a list of values, got {value}" ) if len(operand) == 0 or not all( isinstance(x, type(operand[0])) for x in operand ): - raise ValueError( + raise InvalidArgumentError( f"Expected where operand value to be a non-empty list, and all values to be of the same type " f"got {operand}" ) @@ -443,7 +443,7 @@ def to_proto_where(where: Where) -> chroma_pb.Where: dlo.list_operator = list_operator dc.double_list_operand.CopyFrom(dlo) else: - raise ValueError( + raise InvalidArgumentError( f"Expected where operand value to be a list of strings, ints, or floats, got {operand}" ) elif operator in ["$eq", "$ne", "$gt", "$lt", "$gte", "$lte"]: @@ -456,7 +456,7 @@ def to_proto_where(where: Where) -> chroma_pb.Where: elif operator == "$ne": ssc.comparator = chroma_pb.GenericComparator.NE else: - raise ValueError( + raise InvalidArgumentError( f"Expected where operator to be $eq or $ne, got {operator}" ) dc.single_string_operand.CopyFrom(ssc) @@ -468,7 +468,7 @@ def to_proto_where(where: Where) -> chroma_pb.Where: elif operator == "$ne": sbc.comparator = chroma_pb.GenericComparator.NE else: - raise ValueError( + raise InvalidArgumentError( f"Expected where operator to be $eq or $ne, got {operator}" ) dc.single_bool_operand.CopyFrom(sbc) @@ -488,7 +488,7 @@ def to_proto_where(where: Where) -> chroma_pb.Where: elif operator == "$lte": sic.number_comparator = chroma_pb.NumberComparator.LTE else: - raise ValueError( + raise InvalidArgumentError( f"Expected where operator to be one of $eq, $ne, $gt, $lt, $gte, $lte, got {operator}" ) dc.single_int_operand.CopyFrom(sic) @@ -508,12 +508,12 @@ def to_proto_where(where: Where) -> chroma_pb.Where: elif operator == "$lte": sfc.number_comparator = chroma_pb.NumberComparator.LTE else: - raise ValueError( + raise InvalidArgumentError( f"Expected where operator to be one of $eq, $ne, $gt, $lt, $gte, $lte, got {operator}" ) dc.single_double_operand.CopyFrom(sfc) else: - raise ValueError( + raise InvalidArgumentError( f"Expected where operand value to be a string, int, or float, got {operand}" ) else: @@ -528,7 +528,7 @@ def to_proto_where(where: Where) -> chroma_pb.Where: def to_proto_where_document(where_document: WhereDocument) -> chroma_pb.WhereDocument: response = chroma_pb.WhereDocument() if len(where_document) != 1: - raise ValueError( + raise InvalidArgumentError( f"Expected where_document to have exactly one operator, got {where_document}" ) @@ -536,7 +536,7 @@ def to_proto_where_document(where_document: WhereDocument) -> chroma_pb.WhereDoc if operator == "$and" or operator == "$or": # Nested "$and" or "$or" expression. if not isinstance(operand, list): - raise ValueError( + raise InvalidArgumentError( f"Expected where_document value for $and or $or to be a list of where_document expressions, got {operand}" ) children: chroma_pb.WhereDocumentChildren = chroma_pb.WhereDocumentChildren( @@ -552,7 +552,7 @@ def to_proto_where_document(where_document: WhereDocument) -> chroma_pb.WhereDoc # Direct "$contains" or "$not_contains" comparison to a single # value. if not isinstance(operand, str): - raise ValueError( + raise InvalidArgumentError( f"Expected where_document operand to be a string, got {operand}" ) dwd = chroma_pb.DirectWhereDocument() @@ -562,7 +562,7 @@ def to_proto_where_document(where_document: WhereDocument) -> chroma_pb.WhereDoc elif operator == "$not_contains": dwd.operator = chroma_pb.WhereDocumentOperator.NOT_CONTAINS else: - raise ValueError( + raise InvalidArgumentError( f"Expected where_document operator to be one of $contains, $not_contains, got {operator}" ) response.direct.CopyFrom(dwd) diff --git a/chromadb/segment/impl/distributed/segment_directory.py b/chromadb/segment/impl/distributed/segment_directory.py index 097b3b38566..373bdecef1d 100644 --- a/chromadb/segment/impl/distributed/segment_directory.py +++ b/chromadb/segment/impl/distributed/segment_directory.py @@ -82,7 +82,7 @@ def __init__(self, system: System): @override def start(self) -> None: if self._memberlist_name is None: - raise ValueError("Memberlist name must be set before starting") + raise InvalidArgumentError("Memberlist name must be set before starting") self.get_memberlist() self._done_waiting_for_reset.clear() self._watch_worker_memberlist() @@ -108,7 +108,7 @@ def reset_state(self) -> None: # get propagated back again # Note that the component must be running in order to reset the state if not self._system.settings.require("allow_reset"): - raise ValueError( + raise InvalidArgumentError( "Resetting the database is not allowed. Set `allow_reset` to true in the config in tests or other non-production environments where reset should be permitted." ) if self._memberlist_name: @@ -252,7 +252,7 @@ def stop(self) -> None: @override def get_segment_endpoint(self, segment: Segment) -> str: if self._curr_memberlist is None or len(self._curr_memberlist) == 0: - raise ValueError("Memberlist is not initialized") + raise InvalidArgumentError("Memberlist is not initialized") # Query to the same collection should end up on the same endpoint assignment = assign( segment["collection"].hex, diff --git a/chromadb/segment/impl/manager/local.py b/chromadb/segment/impl/manager/local.py index 06b152cc7f3..270d10d8028 100644 --- a/chromadb/segment/impl/manager/local.py +++ b/chromadb/segment/impl/manager/local.py @@ -204,7 +204,7 @@ def get_segment(self, collection_id: UUID, type: Type[S]) -> S: elif type == VectorReader: scope = SegmentScope.VECTOR else: - raise ValueError(f"Invalid segment type: {type}") + raise InvalidArgumentError(f"Invalid segment type: {type}") segment = self.segment_cache[scope].get(collection_id) if segment is None: diff --git a/chromadb/segment/impl/metadata/sqlite.py b/chromadb/segment/impl/metadata/sqlite.py index d54dc95f342..80c3d03c7ba 100644 --- a/chromadb/segment/impl/metadata/sqlite.py +++ b/chromadb/segment/impl/metadata/sqlite.py @@ -129,7 +129,7 @@ def get_metadata( offset = offset or 0 if limit < 0: - raise ValueError("Limit cannot be negative") + raise InvalidArgumentError("Limit cannot be negative") select_clause = [ embeddings_t.id, @@ -587,8 +587,8 @@ def _where_doc_criterion( else embeddings_t.id.notin(sq) ) else: - raise ValueError(f"Unknown where_doc operator {k}") - raise ValueError("Empty where_doc") + raise InvalidArgumentError(f"Unknown where_doc operator {k}") + raise InvalidArgumentError("Empty where_doc") @trace_method("SqliteMetadataSegment.delete", OpenTelemetryGranularity.ALL) @override diff --git a/chromadb/segment/impl/vector/hnsw_params.py b/chromadb/segment/impl/vector/hnsw_params.py index 4387f188edf..ac284f7654a 100644 --- a/chromadb/segment/impl/vector/hnsw_params.py +++ b/chromadb/segment/impl/vector/hnsw_params.py @@ -38,9 +38,9 @@ def _validate(metadata: Dict[str, Any], validators: Dict[str, Validator]) -> Non # Validate it for param, value in metadata.items(): if param not in validators: - raise ValueError(f"Unknown HNSW parameter: {param}") + raise InvalidArgumentError(f"Unknown HNSW parameter: {param}") if not validators[param](value): - raise ValueError(f"Invalid value for HNSW parameter: {param} = {value}") + raise InvalidArgumentError(f"Invalid value for HNSW parameter: {param} = {value}") class HnswParams(Params): diff --git a/chromadb/server/fastapi/__init__.py b/chromadb/server/fastapi/__init__.py index 9b3e725b2d7..e748e826015 100644 --- a/chromadb/server/fastapi/__init__.py +++ b/chromadb/server/fastapi/__init__.py @@ -109,12 +109,12 @@ async def catch_exceptions_middleware( return await call_next(request) except ChromaError as e: return fastapi_json_response(e) - except ValueError as e: + except InvalidArgumentError as e: return ORJSONResponse( content={"error": "InvalidArgumentError", "message": str(e)}, status_code=400, ) - except TypeError as e: + except InvalidArgumentError as e: return ORJSONResponse( content={"error": "InvalidArgumentError", "message": str(e)}, status_code=400, diff --git a/chromadb/telemetry/product/events.py b/chromadb/telemetry/product/events.py index 568a84ca7c7..42b91ff8126 100644 --- a/chromadb/telemetry/product/events.py +++ b/chromadb/telemetry/product/events.py @@ -70,7 +70,7 @@ def batch_key(self) -> str: def batch(self, other: "ProductTelemetryEvent") -> "CollectionAddEvent": if not self.batch_key == other.batch_key: - raise ValueError("Cannot batch events") + raise InvalidArgumentError("Cannot batch events") other = cast(CollectionAddEvent, other) total_amount = self.add_amount + other.add_amount return CollectionAddEvent( @@ -118,7 +118,7 @@ def batch_key(self) -> str: def batch(self, other: "ProductTelemetryEvent") -> "CollectionUpdateEvent": if not self.batch_key == other.batch_key: - raise ValueError("Cannot batch events") + raise InvalidArgumentError("Cannot batch events") other = cast(CollectionUpdateEvent, other) total_amount = self.update_amount + other.update_amount return CollectionUpdateEvent( @@ -176,7 +176,7 @@ def batch_key(self) -> str: def batch(self, other: "ProductTelemetryEvent") -> "CollectionQueryEvent": if not self.batch_key == other.batch_key: - raise ValueError("Cannot batch events") + raise InvalidArgumentError("Cannot batch events") other = cast(CollectionQueryEvent, other) total_amount = self.query_amount + other.query_amount return CollectionQueryEvent( @@ -228,7 +228,7 @@ def batch_key(self) -> str: def batch(self, other: "ProductTelemetryEvent") -> "CollectionGetEvent": if not self.batch_key == other.batch_key: - raise ValueError("Cannot batch events") + raise InvalidArgumentError("Cannot batch events") other = cast(CollectionGetEvent, other) total_amount = self.ids_count + other.ids_count return CollectionGetEvent( diff --git a/chromadb/test/api/test_types.py b/chromadb/test/api/test_types.py index d2c6ebfb4fc..adebca648ae 100644 --- a/chromadb/test/api/test_types.py +++ b/chromadb/test/api/test_types.py @@ -40,6 +40,6 @@ def __call__(self, input: Documents) -> Embeddings: return cast(Embeddings, invalid_embedding) ef = TestEmbeddingFunction() - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: ef(random_documents()) - assert e.type is ValueError + assert e.type is InvalidArgumentError diff --git a/chromadb/test/client/create_http_client_with_basic_auth.py b/chromadb/test/client/create_http_client_with_basic_auth.py index 86be4727c5c..63d7f2c2ac6 100644 --- a/chromadb/test/client/create_http_client_with_basic_auth.py +++ b/chromadb/test/client/create_http_client_with_basic_auth.py @@ -18,7 +18,7 @@ def main() -> None: chroma_client_auth_credentials="admin:testDb@home2", ), ) - except ValueError: + except InvalidArgumentError: # We don't expect to be able to connect to Chroma. We just want to make sure # there isn't an ImportError. sys.exit(0) diff --git a/chromadb/test/configurations/test_configurations.py b/chromadb/test/configurations/test_configurations.py index 0d952957a73..87d9ea1a4ae 100644 --- a/chromadb/test/configurations/test_configurations.py +++ b/chromadb/test/configurations/test_configurations.py @@ -56,7 +56,7 @@ def test_set_values() -> None: def test_get_invalid_parameter() -> None: test_configuration = TestConfiguration() - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): test_configuration.get_parameter("invalid_name") @@ -75,13 +75,13 @@ def test_validation() -> None: invalid_parameter_values = [ ConfigurationParameter(name="static_str_value", value=1.0) ] - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): TestConfiguration(parameters=invalid_parameter_values) invalid_parameter_names = [ ConfigurationParameter(name="invalid_name", value="some_value") ] - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): TestConfiguration(parameters=invalid_parameter_names) @@ -101,10 +101,10 @@ def configuration_validator(self) -> None: if self.parameter_map.get("foo") != "bar": raise InvalidConfigurationError("foo must be 'bar'") - with pytest.raises(ValueError, match="foo must be 'bar'"): + with pytest.raises(InvalidArgumentError, match="foo must be 'bar'"): FooConfiguration(parameters=[ConfigurationParameter(name="foo", value="baz")]) def test_hnsw_validation() -> None: - with pytest.raises(ValueError, match="must be less than or equal"): + with pytest.raises(InvalidArgumentError, match="must be less than or equal"): HNSWConfiguration(batch_size=500, sync_threshold=100) diff --git a/chromadb/test/conftest.py b/chromadb/test/conftest.py index 47e03c11fe3..22c3361832d 100644 --- a/chromadb/test/conftest.py +++ b/chromadb/test/conftest.py @@ -45,7 +45,7 @@ CURRENT_PRESET = os.getenv("PROPERTY_TESTING_PRESET", "fast") if CURRENT_PRESET not in VALID_PRESETS: - raise ValueError( + raise InvalidArgumentError( f"Invalid property testing preset: {CURRENT_PRESET}. Must be one of {VALID_PRESETS}." ) diff --git a/chromadb/test/data_loader/test_data_loader.py b/chromadb/test/data_loader/test_data_loader.py index a19b519a6fb..4c266a79b96 100644 --- a/chromadb/test/data_loader/test_data_loader.py +++ b/chromadb/test/data_loader/test_data_loader.py @@ -59,14 +59,14 @@ def test_without_data_loader( record_set = record_set_with_uris(n=n_examples) # Can't embed data in URIs without a data loader - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection_without_data_loader.add( ids=record_set["ids"], uris=record_set["uris"], ) # Can't get data from URIs without a data loader - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection_without_data_loader.get(include=["data"]) diff --git a/chromadb/test/ef/test_default_ef.py b/chromadb/test/ef/test_default_ef.py index a80ccd2813b..b461c394ebc 100644 --- a/chromadb/test/ef/test_default_ef.py +++ b/chromadb/test/ef/test_default_ef.py @@ -28,7 +28,7 @@ def unique_by(x: Hashable) -> Hashable: ) ) def test_unavailable_provider_multiple(providers: List[str]) -> None: - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: ef = ONNXMiniLM_L6_V2(preferred_providers=providers) ef(["test"]) assert "Preferred providers must be subset of available providers" in str(e.value) @@ -62,7 +62,7 @@ def test_warning_no_providers_supplied() -> None: ).filter(lambda x: len(x) > len(set(x))) ) def test_provider_repeating(providers: List[str]) -> None: - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: ef = ONNXMiniLM_L6_V2(preferred_providers=providers) ef(["test"]) assert "Preferred providers must be unique" in str(e.value) @@ -71,7 +71,7 @@ def test_provider_repeating(providers: List[str]) -> None: def test_invalid_sha256() -> None: ef = ONNXMiniLM_L6_V2() shutil.rmtree(ef.DOWNLOAD_PATH) # clean up any existing models - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: ef._MODEL_SHA256 = "invalid" ef(["test"]) assert "does not match expected SHA256 hash" in str(e.value) diff --git a/chromadb/test/ef/test_multimodal_ef.py b/chromadb/test/ef/test_multimodal_ef.py index 44ef4ad9f5b..59f7125f0bd 100644 --- a/chromadb/test/ef/test_multimodal_ef.py +++ b/chromadb/test/ef/test_multimodal_ef.py @@ -69,7 +69,7 @@ def test_multimodal( # Trying to add a document and an image at the same time should fail with pytest.raises( - ValueError, + InvalidArgumentError, # This error string may be in any order match=r"Exactly one of (images|documents|uris)(?:, (images|documents|uris))?(?:, (images|documents|uris))? must be provided in add\.", ): @@ -119,7 +119,7 @@ def test_multimodal( ] # Querying with both images and documents should fail - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): multimodal_collection.query( query_images=[query_image], query_texts=[query_document] ) diff --git a/chromadb/test/property/strategies.py b/chromadb/test/property/strategies.py index 710de47d4c1..b8ff7dbe5f2 100644 --- a/chromadb/test/property/strategies.py +++ b/chromadb/test/property/strategies.py @@ -300,7 +300,7 @@ def collections( use_persistent_hnsw_params = draw(with_persistent_hnsw_params) if use_persistent_hnsw_params and not with_hnsw_params: - raise ValueError( + raise InvalidArgumentError( "with_persistent_hnsw_params requires with_hnsw_params to be true" ) diff --git a/chromadb/test/property/test_client_url.py b/chromadb/test/property/test_client_url.py index cc5df1e0514..f73ec99f45b 100644 --- a/chromadb/test/property/test_client_url.py +++ b/chromadb/test/property/test_client_url.py @@ -124,7 +124,7 @@ def test_resolve_invalid( ssl_enabled: bool, default_api_path: Optional[str], ) -> None: - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: FastAPI.resolve_url( chroma_server_host=hostname, chroma_server_http_port=port, diff --git a/chromadb/test/property/test_collections_with_database_tenant_overwrite.py b/chromadb/test/property/test_collections_with_database_tenant_overwrite.py index e4844dcca2f..3fc34c9b494 100644 --- a/chromadb/test/property/test_collections_with_database_tenant_overwrite.py +++ b/chromadb/test/property/test_collections_with_database_tenant_overwrite.py @@ -105,7 +105,7 @@ def set_tenant_model( # thanks to the above overriding of get_tenant_model(), # the underlying state machine test should always expect an error # when it sends the request, so shouldn't try to update the model. - raise ValueError("trying to overwrite the model for singleton??") + raise InvalidArgumentError("trying to overwrite the model for singleton??") self.tenant_to_database_to_model[tenant] = model @overrides @@ -121,7 +121,7 @@ def set_database_model_for_tenant( # thanks to the above overriding of has_database_for_tenant(), # the underlying state machine test should always expect an error # when it sends the request, so shouldn't try to update the model. - raise ValueError("trying to overwrite the model for singleton??") + raise InvalidArgumentError("trying to overwrite the model for singleton??") self.tenant_to_database_to_model[tenant][database] = database_model @overrides diff --git a/chromadb/test/property/test_embeddings.py b/chromadb/test/property/test_embeddings.py index 189308b2ab9..dd0bb342efd 100644 --- a/chromadb/test/property/test_embeddings.py +++ b/chromadb/test/property/test_embeddings.py @@ -1156,7 +1156,7 @@ def test_escape_chars_in_ids(client: ClientAPI) -> None: def test_delete_empty_fails(client: ClientAPI) -> None: reset(client) coll = client.create_collection(name="foo") - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): coll.delete() @@ -1234,7 +1234,7 @@ def test_autocasting_validate_embeddings_incompatible_types( unsupported_types: List[Any], ) -> None: embds = strategies.create_embeddings(10, 10, unsupported_types) - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: validate_embeddings(cast(Embeddings, normalize_embeddings(embds))) assert ( @@ -1245,7 +1245,7 @@ def test_autocasting_validate_embeddings_incompatible_types( def test_0dim_embedding_validation() -> None: embds: Embeddings = [np.array([])] - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: validate_embeddings(embds) assert ( "Expected each embedding in the embeddings to be a 1-dimensional numpy array with at least 1 int/float value. Got a 1-dimensional numpy array with no values at pos" diff --git a/chromadb/test/property/test_filtering.py b/chromadb/test/property/test_filtering.py index df94ed59fe8..ccc6e28c6e1 100644 --- a/chromadb/test/property/test_filtering.py +++ b/chromadb/test/property/test_filtering.py @@ -76,7 +76,7 @@ def _filter_where_clause(clause: Where, metadata: Optional[Metadata]) -> bool: elif op == "$lte": return key in metadata and metadata[key] <= val else: - raise ValueError("Unknown operator: {}".format(key)) + raise InvalidArgumentError("Unknown operator: {}".format(key)) def _filter_where_doc_clause(clause: WhereDocument, doc: Document) -> bool: @@ -110,7 +110,7 @@ def _filter_where_doc_clause(clause: WhereDocument, doc: Document) -> bool: return re.search(expr, doc) is None return expr not in doc else: - raise ValueError("Unknown operator: {}".format(key)) + raise InvalidArgumentError("Unknown operator: {}".format(key)) EMPTY_DICT: Dict[Any, Any] = {} diff --git a/chromadb/test/segment/test_metadata.py b/chromadb/test/segment/test_metadata.py index bb0f40e4234..9df465efa4f 100644 --- a/chromadb/test/segment/test_metadata.py +++ b/chromadb/test/segment/test_metadata.py @@ -811,7 +811,7 @@ def test_limit( assert len(res) == 3 # if limit is negative, throw error - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): segment.get_metadata(limit=-1, request_version_context=request_version_context) # if offset is more than number of results, return empty list @@ -998,7 +998,7 @@ def test_include_metadata( def test_metadata_validation_forbidden_key() -> None: - with pytest.raises(ValueError, match="chroma:document"): + with pytest.raises(InvalidArgumentError, match="chroma:document"): validate_metadata( {"chroma:document": "this is not the document you are looking for"} ) diff --git a/chromadb/test/test_api.py b/chromadb/test/test_api.py index 0be44498e32..420149cd348 100644 --- a/chromadb/test/test_api.py +++ b/chromadb/test/test_api.py @@ -710,7 +710,7 @@ def test_metadata_update_get_int_float(client): def test_metadata_validation_add(client): client.reset() collection = client.create_collection("test_metadata_validation") - with pytest.raises(ValueError, match="metadata"): + with pytest.raises(InvalidArgumentError, match="metadata"): collection.add(**bad_metadata_records) @@ -718,21 +718,21 @@ def test_metadata_validation_update(client): client.reset() collection = client.create_collection("test_metadata_validation") collection.add(**metadata_records) - with pytest.raises(ValueError, match="metadata"): + with pytest.raises(InvalidArgumentError, match="metadata"): collection.update(ids=["id1"], metadatas={"value": {"nested": "5"}}) def test_where_validation_get(client): client.reset() collection = client.create_collection("test_where_validation") - with pytest.raises(ValueError, match="where"): + with pytest.raises(InvalidArgumentError, match="where"): collection.get(where={"value": {"nested": "5"}}) def test_where_validation_query(client): client.reset() collection = client.create_collection("test_where_validation") - with pytest.raises(ValueError, match="where"): + with pytest.raises(InvalidArgumentError, match="where"): collection.query(query_embeddings=[0, 0, 0], where={"value": {"nested": "5"}}) @@ -800,39 +800,39 @@ def test_where_valid_operators(client): client.reset() collection = client.create_collection("test_where_valid_operators") collection.add(**operator_records) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where={"int_value": {"$invalid": 2}}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where={"int_value": {"$lt": "2"}}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where={"int_value": {"$lt": 2, "$gt": 1}}) # Test invalid $and, $or - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where={"$and": {"int_value": {"$lt": 2}}}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get( where={"int_value": {"$lt": 2}, "$or": {"int_value": {"$gt": 1}}} ) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get( where={"$gt": [{"int_value": {"$lt": 2}}, {"int_value": {"$gt": 1}}]} ) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where={"$or": [{"int_value": {"$lt": 2}}]}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where={"$or": []}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where={"a": {"$contains": "test"}}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get( where={ "$or": [ @@ -883,31 +883,31 @@ def test_query_document_valid_operators(client): client.reset() collection = client.create_collection("test_where_valid_operators") collection.add(**operator_records) - with pytest.raises(ValueError, match="where document"): + with pytest.raises(InvalidArgumentError, match="where document"): collection.get(where_document={"$lt": {"$nested": 2}}) - with pytest.raises(ValueError, match="where document"): + with pytest.raises(InvalidArgumentError, match="where document"): collection.query(query_embeddings=[0, 0, 0], where_document={"$contains": 2}) - with pytest.raises(ValueError, match="where document"): + with pytest.raises(InvalidArgumentError, match="where document"): collection.get(where_document={"$contains": []}) # Test invalid $and, $or - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where_document={"$and": {"$unsupported": "doc"}}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get( where_document={"$or": [{"$unsupported": "doc"}, {"$unsupported": "doc"}]} ) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where_document={"$or": [{"$contains": "doc"}]}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get(where_document={"$or": []}) - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): collection.get( where_document={ "$or": [{"$and": [{"$contains": "doc"}]}, {"$contains": "doc"}] @@ -1175,10 +1175,10 @@ def test_get_include(client): assert items["ids"][0] == "id1" assert items["included"] == [] - with pytest.raises(ValueError, match="include"): + with pytest.raises(InvalidArgumentError, match="include"): items = collection.get(include=["metadatas", "undefined"]) - with pytest.raises(ValueError, match="include"): + with pytest.raises(InvalidArgumentError, match="include"): items = collection.get(include=None) @@ -1207,17 +1207,17 @@ def test_invalid_id(client): client.reset() collection = client.create_collection("test_invalid_id") # Add with non-string id - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: collection.add(embeddings=[0, 0, 0], ids=[1], metadatas=[{}]) assert "ID" in str(e.value) # Get with non-list id - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: collection.get(ids=1) assert "ID" in str(e.value) # Delete with malformed ids - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: collection.delete(ids=["valid", 0]) assert "ID" in str(e.value) @@ -1430,7 +1430,7 @@ def test_invalid_n_results_param(client): client.reset() collection = client.create_collection("testspace") collection.add(**records) - with pytest.raises(TypeError) as exc: + with pytest.raises(InvalidArgumentError) as exc: collection.query( query_embeddings=[[1.1, 2.3, 3.2]], n_results=-1, @@ -1439,16 +1439,16 @@ def test_invalid_n_results_param(client): assert "Number of requested results -1, cannot be negative, or zero." in str( exc.value ) - assert exc.type == TypeError + assert exc.type == InvalidArgumentError - with pytest.raises(ValueError) as exc: + with pytest.raises(InvalidArgumentError) as exc: collection.query( query_embeddings=[[1.1, 2.3, 3.2]], n_results="one", include=["embeddings", "documents", "metadatas", "distances"], ) assert "int" in str(exc.value) - assert exc.type == ValueError + assert exc.type == InvalidArgumentError initial_records = { @@ -1549,12 +1549,12 @@ def test_invalid_embeddings(client): "embeddings": [["0", "0", "0"], ["1.2", "2.24", "3.2"]], "ids": ["id1", "id2"], } - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: collection.add(**invalid_records) assert "embedding" in str(e.value) # Query with invalid embeddings - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: collection.query( query_embeddings=[["1.1", "2.3", "3.2"]], n_results=1, @@ -1566,7 +1566,7 @@ def test_invalid_embeddings(client): "embeddings": [[[0], [0], [0]], [[1.2], [2.24], [3.2]]], "ids": ["id1", "id2"], } - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: collection.update(**invalid_records) assert "embedding" in str(e.value) @@ -1575,7 +1575,7 @@ def test_invalid_embeddings(client): "embeddings": [[[1.1, 2.3, 3.2]], [[1.2, 2.24, 3.2]]], "ids": ["id1", "id2"], } - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: collection.upsert(**invalid_records) assert "embedding" in str(e.value) @@ -1617,7 +1617,7 @@ def test_ssl_self_signed_without_ssl_verify(client_ssl): pytest.skip("Skipping test for integration test") client_ssl.heartbeat() _port = client_ssl._server._settings.chroma_server_http_port - with pytest.raises(ValueError) as e: + with pytest.raises(InvalidArgumentError) as e: chromadb.HttpClient(ssl=True, port=_port) stack_trace = traceback.format_exception( type(e.value), e.value, e.value.__traceback__ diff --git a/chromadb/test/test_chroma.py b/chromadb/test/test_chroma.py index 89b4ae924eb..0de1966f2a6 100644 --- a/chromadb/test/test_chroma.py +++ b/chromadb/test/test_chroma.py @@ -100,7 +100,7 @@ def test_settings_pass_to_fastapi(self, mock: Mock) -> None: def test_legacy_values() -> None: - with pytest.raises(ValueError): + with pytest.raises(InvalidArgumentError): client = chromadb.Client( chromadb.config.Settings( chroma_api_impl="chromadb.api.local.LocalAPI", diff --git a/chromadb/test/test_client.py b/chromadb/test/test_client.py index f8180f9ca26..2fe6615d519 100644 --- a/chromadb/test/test_client.py +++ b/chromadb/test/test_client.py @@ -79,7 +79,7 @@ def test_http_client_with_inconsistent_host_settings( ) -> None: try: http_api_factory(settings=Settings(chroma_server_host="127.0.0.1")) - except ValueError as e: + except InvalidArgumentError as e: assert ( str(e) == "Chroma server host provided in settings[127.0.0.1] is different to the one provided in HttpClient: [localhost]" @@ -96,7 +96,7 @@ def test_http_client_with_inconsistent_port_settings( chroma_server_http_port=8001, ), ) - except ValueError as e: + except InvalidArgumentError as e: assert ( str(e) == "Chroma server http port provided in settings[8001] is different to the one provided in HttpClient: [8002]" diff --git a/chromadb/utils/data_loaders.py b/chromadb/utils/data_loaders.py index 82ea894aa9a..a0e4a3abcd6 100644 --- a/chromadb/utils/data_loaders.py +++ b/chromadb/utils/data_loaders.py @@ -12,7 +12,7 @@ def __init__(self, max_workers: int = multiprocessing.cpu_count()) -> None: self._PILImage = importlib.import_module("PIL.Image") self._max_workers = max_workers except ImportError: - raise ValueError( + raise InvalidArgumentError( "The PIL python package is not installed. Please install it with `pip install pillow`" ) diff --git a/chromadb/utils/embedding_functions/chroma_langchain_embedding_function.py b/chromadb/utils/embedding_functions/chroma_langchain_embedding_function.py index 445cca5b128..e61562c6400 100644 --- a/chromadb/utils/embedding_functions/chroma_langchain_embedding_function.py +++ b/chromadb/utils/embedding_functions/chroma_langchain_embedding_function.py @@ -10,7 +10,7 @@ def create_langchain_embedding(langchain_embdding_fn: Any): # type: ignore try: from langchain_core.embeddings import Embeddings as LangchainEmbeddings except ImportError: - raise ValueError( + raise InvalidArgumentError( "The langchain_core python package is not installed. Please install it with `pip install langchain-core`" ) @@ -40,7 +40,7 @@ def embed_image(self, uris: List[str]) -> List[List[float]]: if hasattr(self.embedding_function, "embed_image"): return self.embedding_function.embed_image(uris) # type: ignore else: - raise ValueError( + raise InvalidArgumentError( "The provided embedding function does not support image embeddings." ) diff --git a/chromadb/utils/embedding_functions/cohere_embedding_function.py b/chromadb/utils/embedding_functions/cohere_embedding_function.py index 6e34b1a7509..eeb01ba887e 100644 --- a/chromadb/utils/embedding_functions/cohere_embedding_function.py +++ b/chromadb/utils/embedding_functions/cohere_embedding_function.py @@ -10,7 +10,7 @@ def __init__(self, api_key: str, model_name: str = "large"): try: import cohere except ImportError: - raise ValueError( + raise InvalidArgumentError( "The cohere python package is not installed. Please install it with `pip install cohere`" ) diff --git a/chromadb/utils/embedding_functions/google_embedding_function.py b/chromadb/utils/embedding_functions/google_embedding_function.py index 0534d790674..beb66db3ff0 100644 --- a/chromadb/utils/embedding_functions/google_embedding_function.py +++ b/chromadb/utils/embedding_functions/google_embedding_function.py @@ -12,15 +12,15 @@ class GooglePalmEmbeddingFunction(EmbeddingFunction[Documents]): def __init__(self, api_key: str, model_name: str = "models/embedding-gecko-001"): if not api_key: - raise ValueError("Please provide a PaLM API key.") + raise InvalidArgumentError("Please provide a PaLM API key.") if not model_name: - raise ValueError("Please provide the model name.") + raise InvalidArgumentError("Please provide the model name.") try: import google.generativeai as palm except ImportError: - raise ValueError( + raise InvalidArgumentError( "The Google Generative AI python package is not installed. Please install it with `pip install google-generativeai`" ) @@ -49,15 +49,15 @@ def __init__( task_type: str = "RETRIEVAL_DOCUMENT", ): if not api_key: - raise ValueError("Please provide a Google API key.") + raise InvalidArgumentError("Please provide a Google API key.") if not model_name: - raise ValueError("Please provide the model name.") + raise InvalidArgumentError("Please provide the model name.") try: import google.generativeai as genai except ImportError: - raise ValueError( + raise InvalidArgumentError( "The Google Generative AI python package is not installed. Please install it with `pip install google-generativeai`" ) diff --git a/chromadb/utils/embedding_functions/instructor_embedding_function.py b/chromadb/utils/embedding_functions/instructor_embedding_function.py index 18d13d8ec0b..0c5d0b27148 100644 --- a/chromadb/utils/embedding_functions/instructor_embedding_function.py +++ b/chromadb/utils/embedding_functions/instructor_embedding_function.py @@ -18,7 +18,7 @@ def __init__( try: from InstructorEmbedding import INSTRUCTOR except ImportError: - raise ValueError( + raise InvalidArgumentError( "The InstructorEmbedding python package is not installed. Please install it with `pip install InstructorEmbedding`" ) self._model = INSTRUCTOR(model_name, device=device) diff --git a/chromadb/utils/embedding_functions/onnx_mini_lm_l6_v2.py b/chromadb/utils/embedding_functions/onnx_mini_lm_l6_v2.py index 2bef446116c..adbe311e2c7 100644 --- a/chromadb/utils/embedding_functions/onnx_mini_lm_l6_v2.py +++ b/chromadb/utils/embedding_functions/onnx_mini_lm_l6_v2.py @@ -51,32 +51,32 @@ def __init__(self, preferred_providers: Optional[List[str]] = None) -> None: if preferred_providers and not all( [isinstance(i, str) for i in preferred_providers] ): - raise ValueError("Preferred providers must be a list of strings") + raise InvalidArgumentError("Preferred providers must be a list of strings") # check for duplicate providers if preferred_providers and len(preferred_providers) != len( set(preferred_providers) ): - raise ValueError("Preferred providers must be unique") + raise InvalidArgumentError("Preferred providers must be unique") self._preferred_providers = preferred_providers try: # Equivalent to import onnxruntime self.ort = importlib.import_module("onnxruntime") except ImportError: - raise ValueError( + raise InvalidArgumentError( "The onnxruntime python package is not installed. Please install it with `pip install onnxruntime`" ) try: # Equivalent to from tokenizers import Tokenizer self.Tokenizer = importlib.import_module("tokenizers").Tokenizer except ImportError: - raise ValueError( + raise InvalidArgumentError( "The tokenizers python package is not installed. Please install it with `pip install tokenizers`" ) try: # Equivalent to from tqdm import tqdm self.tqdm = importlib.import_module("tqdm").tqdm except ImportError: - raise ValueError( + raise InvalidArgumentError( "The tqdm python package is not installed. Please install it with `pip install tqdm`" ) @@ -112,7 +112,7 @@ def _download(self, url: str, fname: str, chunk_size: int = 1024) -> None: if not _verify_sha256(fname, self._MODEL_SHA256): # if the integrity of the file is not verified, remove it os.remove(fname) - raise ValueError( + raise InvalidArgumentError( f"Downloaded file {fname} does not match expected SHA256 hash. Corrupted download or malicious file." ) @@ -178,7 +178,7 @@ def model(self) -> "InferenceSession": # noqa F821 elif not set(self._preferred_providers).issubset( set(self.ort.get_available_providers()) ): - raise ValueError( + raise InvalidArgumentError( f"Preferred providers must be subset of available providers: {self.ort.get_available_providers()}" ) diff --git a/chromadb/utils/embedding_functions/open_clip_embedding_function.py b/chromadb/utils/embedding_functions/open_clip_embedding_function.py index a261e4ed2e7..234735edb4e 100644 --- a/chromadb/utils/embedding_functions/open_clip_embedding_function.py +++ b/chromadb/utils/embedding_functions/open_clip_embedding_function.py @@ -27,20 +27,20 @@ def __init__( try: import open_clip except ImportError: - raise ValueError( + raise InvalidArgumentError( "The open_clip python package is not installed. Please install it with `pip install open-clip-torch`. https://github.com/mlfoundations/open_clip" ) try: self._torch = importlib.import_module("torch") except ImportError: - raise ValueError( + raise InvalidArgumentError( "The torch python package is not installed. Please install it with `pip install torch`" ) try: self._PILImage = importlib.import_module("PIL.Image") except ImportError: - raise ValueError( + raise InvalidArgumentError( "The PIL python package is not installed. Please install it with `pip install pillow`" ) diff --git a/chromadb/utils/embedding_functions/openai_embedding_function.py b/chromadb/utils/embedding_functions/openai_embedding_function.py index ce333cc3bba..a4784ac46bd 100644 --- a/chromadb/utils/embedding_functions/openai_embedding_function.py +++ b/chromadb/utils/embedding_functions/openai_embedding_function.py @@ -46,14 +46,14 @@ def __init__( try: import openai except ImportError: - raise ValueError( + raise InvalidArgumentError( "The openai python package is not installed. Please install it with `pip install openai`" ) self._api_key = api_key or openai.api_key # If the api key is still not set, raise an error if self._api_key is None: - raise ValueError( + raise InvalidArgumentError( "Please provide an OpenAI API key. You can get one at https://platform.openai.com/account/api-keys" ) diff --git a/chromadb/utils/embedding_functions/roboflow_embedding_function.py b/chromadb/utils/embedding_functions/roboflow_embedding_function.py index b118aa01c64..43e945fc87e 100644 --- a/chromadb/utils/embedding_functions/roboflow_embedding_function.py +++ b/chromadb/utils/embedding_functions/roboflow_embedding_function.py @@ -39,7 +39,7 @@ def __init__( try: self._PILImage = importlib.import_module("PIL.Image") except ImportError: - raise ValueError( + raise InvalidArgumentError( "The PIL python package is not installed. Please install it with `pip install pillow`" ) diff --git a/chromadb/utils/embedding_functions/sentence_transformer_embedding_function.py b/chromadb/utils/embedding_functions/sentence_transformer_embedding_function.py index 7a2b57c6ae9..71e50789556 100644 --- a/chromadb/utils/embedding_functions/sentence_transformer_embedding_function.py +++ b/chromadb/utils/embedding_functions/sentence_transformer_embedding_function.py @@ -31,7 +31,7 @@ def __init__( try: from sentence_transformers import SentenceTransformer except ImportError: - raise ValueError( + raise InvalidArgumentError( "The sentence_transformers python package is not installed. Please install it with `pip install sentence_transformers`" ) self.models[model_name] = SentenceTransformer( diff --git a/chromadb/utils/embedding_functions/text2vec_embedding_function.py b/chromadb/utils/embedding_functions/text2vec_embedding_function.py index 9e4639c23d0..e4863b40261 100644 --- a/chromadb/utils/embedding_functions/text2vec_embedding_function.py +++ b/chromadb/utils/embedding_functions/text2vec_embedding_function.py @@ -11,7 +11,7 @@ def __init__(self, model_name: str = "shibing624/text2vec-base-chinese"): try: from text2vec import SentenceModel except ImportError: - raise ValueError( + raise InvalidArgumentError( "The text2vec python package is not installed. Please install it with `pip install text2vec`" ) self._model = SentenceModel(model_name_or_path=model_name) diff --git a/chromadb/utils/embedding_functions/voyageai_embedding_function.py b/chromadb/utils/embedding_functions/voyageai_embedding_function.py index 65b553f5932..27104fca16e 100644 --- a/chromadb/utils/embedding_functions/voyageai_embedding_function.py +++ b/chromadb/utils/embedding_functions/voyageai_embedding_function.py @@ -10,7 +10,7 @@ def __init__(self, api_key: str, model_name: str): try: import voyageai except ImportError: - raise ValueError( + raise InvalidArgumentError( "The voyageai python package is not installed. Please install it with `pip install voyageai`" ) diff --git a/chromadb/utils/fastapi.py b/chromadb/utils/fastapi.py index 8300880e402..d40ee5ae2c8 100644 --- a/chromadb/utils/fastapi.py +++ b/chromadb/utils/fastapi.py @@ -14,5 +14,5 @@ def fastapi_json_response(error: ChromaError) -> JSONResponse: def string_to_uuid(uuid_str: str) -> UUID: try: return UUID(uuid_str) - except ValueError: + except InvalidArgumentError: raise InvalidUUIDError(f"Could not parse {uuid_str} as a UUID") diff --git a/chromadb/utils/rendezvous_hash.py b/chromadb/utils/rendezvous_hash.py index f21e2863225..abaeea80c17 100644 --- a/chromadb/utils/rendezvous_hash.py +++ b/chromadb/utils/rendezvous_hash.py @@ -23,16 +23,16 @@ def assign( """ if replication > len(members): - raise ValueError( + raise InvalidArgumentError( "Replication factor cannot be greater than the number of members" ) if len(members) == 0: - raise ValueError("Cannot assign key to empty memberlist") + raise InvalidArgumentError("Cannot assign key to empty memberlist") if len(members) == 1: # Don't copy the input list for some safety return [members[0]] if key == "": - raise ValueError("Cannot assign empty key") + raise InvalidArgumentError("Cannot assign empty key") member_score_heap: List[Tuple[int, Member]] = [] for member in members: diff --git a/clients/js/src/ChromaFetch.ts b/clients/js/src/ChromaFetch.ts index b7373f9c14f..d61950edee0 100644 --- a/clients/js/src/ChromaFetch.ts +++ b/clients/js/src/ChromaFetch.ts @@ -5,7 +5,7 @@ import { ChromaForbiddenError, ChromaNotFoundError, ChromaServerError, - ChromaValueError, + ChromaInvalidArgumentError, ChromaError, createErrorByType, ChromaUniqueError, @@ -14,7 +14,7 @@ import { FetchAPI } from "./generated"; function isOfflineError(error: any): boolean { return Boolean( - (error?.name === "TypeError" || error?.name === "FetchError") && + (error?.name === "InvalidArgumentError" || error?.name === "FetchError") && (error.message?.includes("fetch failed") || error.message?.includes("Failed to fetch") || error.message?.includes("ENOTFOUND")), @@ -27,8 +27,8 @@ function parseServerError(error: string | undefined): Error { if (match) { const [, name, message] = match; switch (name) { - case "ValueError": - return new ChromaValueError(message); + case "InvalidArgumentError": + return new ChromaInvalidArgumentError(message); default: return new ChromaError(name, message); } diff --git a/clients/js/src/Errors.ts b/clients/js/src/Errors.ts index 1aa69720004..582a50caddb 100644 --- a/clients/js/src/Errors.ts +++ b/clients/js/src/Errors.ts @@ -57,8 +57,8 @@ export class ChromaNotFoundError extends Error { } } -export class ChromaValueError extends Error { - name = "ChromaValueError"; +export class ChromaInvalidArgumentError extends Error { + name = "ChromaInvalidArgumentError"; constructor(message: string, public readonly cause?: unknown) { super(message); } diff --git a/docs/docs.trychroma.com/markdoc/content/reference/python/client.md b/docs/docs.trychroma.com/markdoc/content/reference/python/client.md index 379d340e918..7333e7c731a 100644 --- a/docs/docs.trychroma.com/markdoc/content/reference/python/client.md +++ b/docs/docs.trychroma.com/markdoc/content/reference/python/client.md @@ -194,7 +194,7 @@ Delete a collection with the given name. **Raises**: -- `ValueError` - If the collection does not exist. +- `InvalidArgumentError` - If the collection does not exist. **Examples**: @@ -313,8 +313,8 @@ Create a new collection with the given name and metadata. **Raises**: -- `ValueError` - If the collection already exists and get_or_create is False. -- `ValueError` - If the collection name is invalid. +- `InvalidArgumentError` - If the collection already exists and get_or_create is False. +- `InvalidArgumentError` - If the collection name is invalid. **Examples**: @@ -356,7 +356,7 @@ Get a collection with the given name. **Raises**: -- `ValueError` - If the collection does not exist +- `InvalidArgumentError` - If the collection does not exist **Examples**: diff --git a/docs/docs.trychroma.com/markdoc/content/reference/python/collection.md b/docs/docs.trychroma.com/markdoc/content/reference/python/collection.md index 208122e6d8f..ff66516e95d 100644 --- a/docs/docs.trychroma.com/markdoc/content/reference/python/collection.md +++ b/docs/docs.trychroma.com/markdoc/content/reference/python/collection.md @@ -46,9 +46,9 @@ Add embeddings to the data store. **Raises**: -- `ValueError` - If you don't provide either embeddings or documents -- `ValueError` - If the length of ids, embeddings, metadatas, or documents don't match -- `ValueError` - If you don't provide an embedding function and don't provide embeddings +- `InvalidArgumentError` - If you don't provide either embeddings or documents +- `InvalidArgumentError` - If the length of ids, embeddings, metadatas, or documents don't match +- `InvalidArgumentError` - If you don't provide an embedding function and don't provide embeddings - `DuplicateIDError` - If you provide an id that already exists ## get @@ -128,8 +128,8 @@ Get the n_results nearest neighbor embeddings for provided query_embeddings or q **Raises**: -- `ValueError` - If you don't provide either query_embeddings or query_texts -- `ValueError` - If you provide both query_embeddings and query_texts +- `InvalidArgumentError` - If you don't provide either query_embeddings or query_texts +- `InvalidArgumentError` - If you provide both query_embeddings and query_texts ## modify