Skip to content

Add a distinct exception for generative query failures - #2210

Open
karthiksenv wants to merge 2 commits into
weaviate:mainfrom
karthiksenv:codex/generative-query-error
Open

karthiksenv wants to merge 2 commits into
weaviate:mainfrom
karthiksenv:codex/generative-query-error

Conversation

@karthiksenv

@karthiksenv karthiksenv commented Oct 17, 2026 •

Copy link
Copy Markdown

Generative-query failures currently raise the same WeaviateQueryError as ordinary searches, so applications cannot select RAG-specific troubleshooting by exception type.

Add WeaviateGenerativeQueryError as a subclass of WeaviateQueryError. Sync and async gRPC searches select it when the request contains the generative field, including deadline expiry and exhausted retries. A shared _search_error helper selects the exception in both clients. Permission errors are handled before that selection.

Compatibility: existing except WeaviateQueryError handlers and isinstance(e, WeaviateQueryError) checks still match. Exact checks such as type(e) is WeaviateQueryError no longer match failed generative requests; use isinstance when subclasses should match. The existing GRPC search error wording is preserved. The message and error attributes retain the original details, and exception chaining preserves the cause. Ordinary searches retain the generic exception.

The exception identifies a failed generative request; retrieval can also fail, so it does not assume the provider caused the failure. The exception documentation includes a catch-order example and troubleshooting guidance.

Closes #818.

Validation of the current commit (a22d4f3):

  • Four mock cases pass on Linux with Python 3.12.13: retry exhaustion and permission handling for sync and async clients.
  • Both integration tests pass against a temporary local Weaviate 1.39.7 server with generative-dummy,generative-anyscale enabled and no provider API key. They check the specialized generative exception, compatibility with the base exception and existing error wording, and the exact generic exception for ordinary queries.
  • Ruff checks and formatting checks pass for all four files changed by the review follow-up; git diff --check passes.

Before the review follow-up, the full Linux unit/mock suite passed with 646 tests passing and 1 skipped. That earlier run covered the previous commit, not the revised test suite.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Orca Security Scan Summary

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

@karthiksenv
karthiksenv marked this pull request as ready for review October 17, 2026 22:20
@weaviate-git-bot

Copy link
Copy Markdown

To avoid any confusion in the future about your contribution to Weaviate, we work with a Contributor License Agreement. If you agree, you can simply add a comment to this PR that you agree with the CLA so that we can merge.

beep boop - the Weaviate bot 👋🤖

PS:
Are you already a member of the Weaviate Forum?

@karthiksenv

Copy link
Copy Markdown
Author

I agree to the Weaviate Contributor License Agreement.

The Main CI workflow is awaiting maintainer approval. Could a maintainer approve the workflow and review this PR? The local Linux unit/mock suite passed with 646 tests passing and 1 skipped, and the before/after behavior was verified against Weaviate 1.39.7 for both sync and async clients.

@karthiksenv

Copy link
Copy Markdown
Author

@dirkkul, could you review this generative-query exception change or route it to the appropriate reviewer? The CLA acknowledgment and local validation are documented above. Please also confirm whether any fork CI approval or additional checks are needed before merge.

@karthiksenv

Copy link
Copy Markdown
Author

@dirkkul, could you review the generative-query exception contract or route it to the Python client reviewer? The new exception remains a subclass of WeaviateQueryError, preserving existing handlers. The CLA acknowledgment, 646-test Linux run, and real-server before/after checks are documented above. Could you also confirm whether the Main workflow still needs fork approval and what remains before merge?

Comment thread weaviate/exceptions.py Outdated
"""

def __init__(self, message: str):
super().__init__(message, "GRPC generative search")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think user code that checks a failed generate call stops matching after an upgrade, in two ways:

  • str(e) reads ... protocol GRPC generative search failed ... instead of ... protocol GRPC search failed ..., so a check like "GRPC search failed" in str(e) stops matching
  • type(e) is WeaviateQueryError turns false, while isinstance still matches

could we keep "GRPC search" as the protocol here? WeaviateGenerativeQueryError already tells generate failures apart. We write the changelog from merged PRs, so could you note the type change in the PR description, and the text change if you keep it?

how I checked

With the mock server from your tests failing every search with INTERNAL generative provider failed, collection.generate.near_text(query="test", single_prompt="Summarize {text}") raises Query call with protocol GRPC search failed with message generative provider failed. on main, and Query call with protocol GRPC generative search failed with message generative provider failed. on this branch. e.message and e.error are generative provider failed on both. A test using pytest.raises(WeaviateQueryError, match="GRPC search") fails the same way. Searching the repo for "GRPC search" and type(e) is WeaviateQueryError outside weaviate/connect/v4.py only finds your new test, so nothing in the client itself breaks. If you keep the old text, the assertion at mock_tests/test_generative_errors.py:96 can check it like test_regular_query_error_is_unchanged does. RELEASING.md has the changelog step. Whoever releases lists the merged PRs and adds the relevant entries to docs/changelog.rst.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I restored the GRPC search wording, so existing message checks still match. The new exception remains a subclass of WeaviateQueryError; exact checks like type(e) is WeaviateQueryError do change. Both integration tests now check the wording and base-class compatibility.

Comment thread weaviate/connect/v4.py Outdated
error = cast(Call, e)
if error.code() == StatusCode.PERMISSION_DENIED:
raise InsufficientPermissionsError(error)
if request.HasField("generative"):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

request.HasField("generative") picks the error class four times, here and in the WeaviateRetryError branch below, and twice in the async grpc_search. could we move that choice into one helper in v4.py?

def _search_error(request: search_get_pb2.SearchRequest, message: str) -> WeaviateQueryError:
    if request.HasField("generative"):
        return WeaviateGenerativeQueryError(message)
    return WeaviateQueryError(message, "GRPC search")

then each site is one line, raise _search_error(request, str(error.details())) from e here and raise _search_error(request, str(e)) from e in the retry branch. Plain search errors get from e too, which only changes their traceback wording. Keeping the four checks inline works too, so this isn't blocking from my side.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done. _search_error now selects the exception in both clients, including retry exhaustion. Permission errors are still handled first.

Comment thread mock_tests/test_generative_errors.py Outdated
("near_media", {"media": "YXVkaW8=", "media_type": NearMediaType.AUDIO}),
],
)
async def test_generative_query_errors(search_service: SearchService, client, method, kwargs):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think most of this file could be one integration test instead. With Configure.Generative.anyscale() and no API key, every generate call fails with "no api key found" before reaching Anyscale. You could check with collection_factory that generate.fetch_objects raises WeaviateGenerativeQueryError on both clients, and that a query with a bad filter still raises WeaviateQueryError itself.

Only the UNAVAILABLE retry and PERMISSION_DENIED mocks would stay, since a real server can't produce those on demand, so 4 cases instead of 36.

sketch
def test_generative_query_error(collection_factory: CollectionFactory) -> None:
    collection = collection_factory(
        properties=[Property(name="text", data_type=DataType.TEXT)],
        generative_config=Configure.Generative.anyscale(),  # no API key, so generation fails
    )
    collection.data.insert({"text": "hello"})
    with pytest.raises(WeaviateGenerativeQueryError):
        collection.generate.fetch_objects(single_prompt="Summarize {text}")
    with pytest.raises(WeaviateQueryError) as exc:
        collection.query.fetch_objects(filters=Filter.by_property("missing").equal(1))
    assert type(exc.value) is WeaviateQueryError


@pytest.mark.asyncio
async def test_generative_query_error_async(async_collection_factory: AsyncCollectionFactory) -> None:
    collection = await async_collection_factory(
        properties=[Property(name="text", data_type=DataType.TEXT)],
        generative_config=Configure.Generative.anyscale(),
    )
    await collection.data.insert({"text": "hello"})
    with pytest.raises(WeaviateGenerativeQueryError):
        await collection.generate.fetch_objects(grouped_task="Summarize")

Both pass against Weaviate 1.39.0 with ENABLE_MODULES=generative-dummy,generative-anyscale, and the default CI server already enables generative-anyscale.

why each mock test can go or should stay
  • test_generative_query_errors (18): the integration test covers the class choice. The nine methods also check that each executor sets generative. If you want to keep that, run it with the sync client only, since both clients share the executors.
  • test_generative_timeout_and_retries (8): only UNAVAILABLE reaches the WeaviateRetryError branch, so keep that one. A server DEADLINE_EXCEEDED takes the same RpcError branch as INTERNAL, and the kwargs parameter changes nothing in grpc_search.
  • test_generative_client_deadline (2): a client deadline also raises an RpcError and takes the same branch, and each case waits out the 1 s query timeout.
  • test_generative_validation_is_unchanged (2): validation runs before any request is sent.
  • test_regular_query_error_is_unchanged (2): the plain query in the integration test covers it.
  • test_generative_permissions_are_unchanged (2): keep it. It checks that the permission check still runs before HasField, and no integration test covers permissions on generate.
  • test_successful_generative_query (2): the success path is unchanged.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I moved the main checks into sync and async integration tests using Anyscale without an API key, and kept just the four retry and permission mock cases. All four mock cases pass, and both integration tests pass against Weaviate 1.39.7.

@karthiksenv
karthiksenv requested a review from dirkkul November 11, 2026 23:11
@karthiksenv

Copy link
Copy Markdown
Author

Hi @dirkkul and @tsmith023, I’ve addressed the three review comments in a22d4f3 and added the compatibility note to the PR description.

The four mock cases pass, and both integration tests pass against Weaviate 1.39.7. Lint and formatting checks pass too.

Could you approve the pending CI workflow and take another look? If everything looks good and the required checks pass, I’d appreciate your approval and a merge. I’m happy to make any final adjustments. Thanks!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] Create a specific set of exception messages for generative queries

3 participants