fix(backend): show a friendly error when KFP is unreachable - #906
fix(backend): show a friendly error when KFP is unreachable#906Bhavd33p wants to merge 2 commits into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
Catch urllib3/requests connection errors raised when the KFP API server can't be reached (wrong host, server down, etc.) and surface them as an RPCServiceUnavailableError with an actionable message instead of the raw exception, matching the existing errors._RPCError pattern. Fixes kubeflow#883 Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: [Bhavdeep Singh] <bhavdeep3singh@gmail.com>
2797f07 to
8e2bcad
Compare
|
@StefanoFioravanzo @ederign Kindly review the changes |
There was a problem hiding this comment.
Pull request overview
Improves RPC feedback when the KFP API server is unreachable.
Changes:
- Converts KFP connection failures into actionable service-unavailable errors.
- Adds unit coverage for connection and unrelated errors.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
kale/rpc/kfp.py |
Adds centralized KFP connection-error handling. |
kale/tests/unit_tests/test_rpc_kfp.py |
Tests friendly error propagation. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def test_create_experiment_kfp_unreachable(_rpc_request): | ||
| """Connection errors raised while checking for an existing experiment propagate.""" | ||
| with ( | ||
| mock.patch("kale.rpc.kfp._get_client", side_effect=_max_retry_error()), |
|
Not a maintainer, just a contributor passing through — this is a nice improvement, the unreachable-KFP dialog is genuinely unhelpful today. I checked the approach against the client internals and it holds up; one suggestion on test coverage. The exception tuple is right. I was initially worried The Main suggestion — the tests may not cover the path users actually hit. All four tests patch if not self._context_setting['namespace'] and self.get_kfp_healthz(...)In the normal Kale setup the namespace is set (from the saved config or The decorator wraps the whole body, so the fix still catches it and the behaviour is correct. But as written the tests only exercise the namespace-unset path, so they'd still pass if the decorator were only applied around client construction. Something like this would pin the common case: def test_list_experiments_kfp_unreachable_on_api_call(_rpc_request):
client = mock.MagicMock()
client.list_experiments.side_effect = _max_retry_error()
with (
mock.patch("kale.rpc.kfp._get_client", return_value=client),
pytest.raises(RPCServiceUnavailableError),
):
kfp.list_experiments(_rpc_request)Minor: worth a one-line comment that Also 👍 on |
The existing tests all patched `_get_client` with a connection error, which only exercises the namespace-unset path: `kfp.Client.__init__` contacts the server solely when no namespace is set, and Kale normally has one, so in practice the client builds fine and `MaxRetryError` is raised by the API call inside the decorated body. Add tests that return a client and fail the API call for `list_experiments`, `get_run` and `create_experiment`. Also make `test_create_experiment_kfp_unreachable` fail on the *second* `_get_client()` call so execution reaches the nested `get_experiment(request, ...)`, pinning the `request` argument there — passing `None` would dereference `None.log` in the decorator and mask the connection error as an AttributeError. Document why `ping()` is intentionally left undecorated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: [Bhavdeep Singh] <bhavdeep3singh@gmail.com>
|
Thanks @harshhh817 — that was a useful read, both points are in (a393c56). Tests now cover the path users actually hit. You were right that
Copilot's note is covered too: Locally: 259 tests pass, @StefanoFioravanzo @ederign this one is ready for review. |
jesuino
left a comment
There was a problem hiding this comment.
I am not able to see this behavior possibly because of the issue created by Adam -> #948 - it would be good if you could address this on this PR as well so we can test all PR!
In any case, do we really need a decorator for this? Shouldn't it be enough to put an exception handler on kfp_client_factory.get_kfp_client when the Client is created? Locally I can see it throws an exception if it can't connect to KFP.
| try: | ||
| return func(request, *args, **kwargs) | ||
| except _KFP_CONNECTION_ERRORS: | ||
| request.log.exception( |
There was a problem hiding this comment.
Isn't this already logged every time a RPC function fails?
Summary
urllib3.exceptions.MaxRetryError/requests.exceptions.ConnectionErrorbubble up, which the frontend displayed as an unhelpful generic error dialog.kale/rpc/kfp.pynow catches those connection errors on every KFP-touching RPC entry point (list_experiments,get_ui_host,get_experiment,create_experiment,upload_pipeline,run_pipeline,get_run) and raises the existing (previously unused)RPCServiceUnavailableError, so the user instead sees:_legacy_executeRpcAndShowRPCErrorinlabextension/src/lib/RPCUtils.tsxalready preferserr_detailswhen showing the dialog.Fixes #883
Test plan
kale/tests/unit_tests/test_rpc_kfp.pycoveringMaxRetryError/ConnectionErrorhandling onlist_experiments,get_run,create_experiment, and confirming unrelated errors (e.g.ValueError) are not swallowed.uv run pytest kale/tests -vv— 254 backend tests pass (2 pre-existing/unrelatede2efailures reproduce identically onmain, confirmed before this change).uv run ruff check kaleanduv run ruff format --check kalepass.