Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions weaviate/collections/grpc/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,15 @@ def __init__(
validate_arguments: bool,
uses_125_api: bool,
uses_127_api: bool,
uses_133_api: bool,
):
super().__init__(weaviate_version, consistency_level, validate_arguments)
self._name: str = name
self._tenant = tenant
self._validate_arguments = validate_arguments
self.__uses_125_api = uses_125_api
self.__uses_127_api = uses_127_api
self.__uses_133_api = uses_133_api

def __parse_near_options(
self,
Expand Down Expand Up @@ -474,6 +476,7 @@ def __create_request(
uses_123_api=True,
uses_125_api=self.__uses_125_api,
uses_127_api=self.__uses_127_api,
uses_133_api=self.__uses_133_api,
collection=self._name,
limit=limit,
offset=offset,
Expand Down
2 changes: 2 additions & 0 deletions weaviate/collections/queries/base_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def __init__(

self.__uses_125_api = connection._weaviate_version.is_at_least(1, 25, 0)
self.__uses_127_api = connection._weaviate_version.is_at_least(1, 27, 0)
self.__uses_133_api = connection._weaviate_version.is_at_least(1, 33, 0)
self._query = _QueryGRPC(
connection._weaviate_version,
self._name,
Expand All @@ -93,6 +94,7 @@ def __init__(
validate_arguments=self._validate_arguments,
uses_125_api=self.__uses_125_api,
uses_127_api=self.__uses_127_api,
uses_133_api=self.__uses_133_api,
)

def __retrieve_timestamp(
Expand Down
53 changes: 42 additions & 11 deletions weaviate/connect/v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
WeaviateGRPCUnavailableError,
WeaviateInvalidInputError,
WeaviateQueryError,
WeaviateQueryThirdPartyError,
WeaviateRetryError,
WeaviateStartUpError,
WeaviateTenantGetError,
Expand Down Expand Up @@ -187,6 +188,38 @@ def set_integrations(self, integrations_config: List[_IntegrationConfig]) -> Non
self._headers.update(integration._to_header())
self.__additional_headers.update(integration._to_header())

def _parse_search_errors(self, sr: search_get_pb2.SearchReply) -> None:
if sr.third_party_error is not None and sr.third_party_error.provider_name != "":
raise WeaviateQueryThirdPartyError(
sr.third_party_error.full_error,
sr.third_party_error.provider_name,
sr.third_party_error.error_from_provider,
sr.third_party_error.status_code,
sr.third_party_error.request_id,
"GRPC search",
)
if sr.internal_error is not None and sr.internal_error != "":
raise WeaviateQueryError(sr.internal_error, "GRPC search")

def _parse_batch_errors(self, res: batch_pb2.BatchObjectsReply) -> Dict[int, str]:
objects: Dict[int, str] = {}
for err in res.errors:
if err.third_party_error is not None:
objects[err.index] = f"""
Provider ({err.third_party_error.provider_name}) service error {err.third_party_error.status_code}

Error details:

'Provider:' {err.third_party_error.provider_name}
'Provider error code:' {err.third_party_error.status_code}
'Provider message:' {err.third_party_error.error_from_provider}

Weaviate error message: {err.third_party_error.full_error}
"""
continue
objects[err.index] = err.error
return objects

@overload
def _make_client(self, colour: Literal["async"]) -> AsyncClient: ...

Expand Down Expand Up @@ -990,11 +1023,14 @@ def grpc_search(self, request: search_get_pb2.SearchRequest) -> search_get_pb2.S
metadata=self.grpc_headers(),
timeout=self.timeout_config.query,
)
return cast(search_get_pb2.SearchReply, res)
sr = cast(search_get_pb2.SearchReply, res)
self._parse_search_errors(sr)
return sr
except RpcError as e:
error = cast(Call, e)
if error.code() == StatusCode.PERMISSION_DENIED:
raise InsufficientPermissionsError(error)

raise WeaviateQueryError(str(error.details()), "GRPC search") # pyright: ignore
except WeaviateRetryError as e:
raise WeaviateQueryError(str(e), "GRPC search") # pyright: ignore
Expand All @@ -1016,11 +1052,7 @@ def grpc_batch_objects(
timeout=timeout,
)
res = cast(batch_pb2.BatchObjectsReply, res)

objects: Dict[int, str] = {}
for err in res.errors:
objects[err.index] = err.error
return objects
return self._parse_batch_errors(res)
except RpcError as e:
error = cast(Call, e)
if error.code() == StatusCode.PERMISSION_DENIED:
Expand Down Expand Up @@ -1176,7 +1208,9 @@ async def grpc_search(
metadata=self.grpc_headers(),
timeout=self.timeout_config.query,
)
return cast(search_get_pb2.SearchReply, res)
sr = cast(search_get_pb2.SearchReply, res)
self._parse_search_errors(sr)
return sr
except AioRpcError as e:
if e.code().name == PERMISSION_DENIED:
raise InsufficientPermissionsError(e)
Expand All @@ -1201,11 +1235,8 @@ async def grpc_batch_objects(
timeout=timeout,
)
res = cast(batch_pb2.BatchObjectsReply, res)
return self._parse_batch_errors(res)

objects: Dict[int, str] = {}
for err in res.errors:
objects[err.index] = err.error
return objects
except AioRpcError as e:
if e.code().name == PERMISSION_DENIED:
raise InsufficientPermissionsError(e)
Expand Down
26 changes: 26 additions & 0 deletions weaviate/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,3 +375,29 @@ def __init__(self) -> None:
super().__init__(
'Weaviate Agents (Alpha) functionality requires additional dependencies. Please install them using: "pip install weaviate-client[agents]"'
)


class WeaviateQueryThirdPartyError(WeaviateQueryError):
"""Is raised if a query (either gRPC or GraphQL) to Weaviate fails in any way."""

def __init__(
self,
full_error: str,
provider_name: str,
provider_error: str,
error_code: int,
request_id: str,
protocol_type: str,
):
request_id_str = f"with request_id {request_id} " if request_id else ""

msg = f"""Query call with protocol GRPC search failed with message Query with request_id {request_id_str} failed:
Provider ({provider_name}) service error {error_code}.
Error details:
{"Provider:":>32} {provider_name}
{"Provider error code:":>32} {error_code}
{"Provider message:":>32} {provider_error}
Weaviate error message:
{full_error}"""
super().__init__(msg, protocol_type)
self.message = msg
8 changes: 5 additions & 3 deletions weaviate/proto/v1/v4/v1/base_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions weaviate/proto/v1/v4/v1/base_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,17 @@ class Vectors(_message.Message):
vector_bytes: bytes
type: Vectors.VectorType
def __init__(self, name: _Optional[str] = ..., index: _Optional[int] = ..., vector_bytes: _Optional[bytes] = ..., type: _Optional[_Union[Vectors.VectorType, str]] = ...) -> None: ...

class ThirdPartyError(_message.Message):
__slots__ = ["provider_name", "error_from_provider", "full_error", "status_code", "request_id"]
PROVIDER_NAME_FIELD_NUMBER: _ClassVar[int]
ERROR_FROM_PROVIDER_FIELD_NUMBER: _ClassVar[int]
FULL_ERROR_FIELD_NUMBER: _ClassVar[int]
STATUS_CODE_FIELD_NUMBER: _ClassVar[int]
REQUEST_ID_FIELD_NUMBER: _ClassVar[int]
provider_name: str
error_from_provider: str
full_error: str
status_code: int
request_id: str
def __init__(self, provider_name: _Optional[str] = ..., error_from_provider: _Optional[str] = ..., full_error: _Optional[str] = ..., status_code: _Optional[int] = ..., request_id: _Optional[str] = ...) -> None: ...
Loading
Loading