Skip to content

chore: improve default error handling 1379 1409#1491

Open
Alexj9837 wants to merge 18 commits intomainfrom
chore/improve-default-error-handling-1379-1409
Open

chore: improve default error handling 1379 1409#1491
Alexj9837 wants to merge 18 commits intomainfrom
chore/improve-default-error-handling-1379-1409

Conversation

@Alexj9837
Copy link
Copy Markdown

Fixes #1379
Fixes #1409

Both issues related to error handling in the REST client.

1379 - Catches 'UnauthorisedAccessErrorexplicitly instead of string-matching onBlueskyRemoteControlError`.

1409 - Expands the exception hierarchy so each
HTTP status code raises a distinct typed exception rather than bundling
everything into BlueskyRemoteControlError.
Tests

Update tests to match new exception signatures
Add missing coverage for 422 non-list detail response
Add missing coverage for streaming error in run command

Alexj9837 and others added 12 commits March 17, 2026 13:33
Poor grammar.

Co-authored-by: Peter Holloway <peter.holloway@diamond.ac.uk>
… having an effect when running plans - you'll still get the Unauthorised request message"
rebased from main to fix merge conflicts

---------

Co-authored-by: Shreelakshmi Iyengar <shreelakshmi.iyengar@diamond.ac.uk>
Co-authored-by: Zoheb Shaikh <zoheb.shaikh@diamond.ac.uk>
Co-authored-by: Daniel Fernandes <65790536+dan-fernandes@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Zoheb Shaikh <26975142+ZohebShaikh@users.noreply.github.com>
Co-authored-by: Abigail Emery <abigail.emery@diamond.ac.uk>
Co-authored-by: oliwenmandiamond <136330507+oliwenmandiamond@users.noreply.github.com>
Co-authored-by: Peter Holloway <peter.holloway@diamond.ac.uk>
Co-authored-by: NeilSmithDLS <118457264+NeilSmithDLS@users.noreply.github.com>
Removed duplicate BlueskyRequestError exception class from rest.py.
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.33%. Comparing base (107d54e) to head (b666346).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1491      +/-   ##
==========================================
+ Coverage   95.25%   95.33%   +0.07%     
==========================================
  Files          43       43              
  Lines        3163     3172       +9     
==========================================
+ Hits         3013     3024      +11     
+ Misses        150      148       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Alexj9837 Alexj9837 marked this pull request as ready for review April 16, 2026 14:47
@Alexj9837 Alexj9837 requested a review from a team as a code owner April 16, 2026 14:47
@tpoliaw
Copy link
Copy Markdown
Contributor

tpoliaw commented Apr 22, 2026

It wasn't mentioned in the original issue but the controller env -r code path doesn't seem to be catching the same errors.

$ uv run blueapi controller env -r
Reloading environment
Traceback (most recent call last):
  File "/dls/athena/blueapi/src/blueapi/client/client.py", line 663, in reload_environment
    status = self._rest.delete_environment()
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/src/blueapi/client/rest.py", line 272, in delete_environment
    return self._request_and_deserialize(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/observability_utils/tracing/decorators.py", line 151, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/src/blueapi/client/rest.py", line 318, in _request_and_deserialize
    raise exception
blueapi.client.rest.UnauthorisedAccessError: (401, '{"detail":"Not authenticated"}')

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/dls/athena/blueapi/.venv/bin/blueapi", line 10, in <module>
    sys.exit(main())
             ^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/click/core.py", line 1485, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/click/core.py", line 1406, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/click/core.py", line 1873, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/click/core.py", line 1873, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/click/core.py", line 1269, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/click/core.py", line 824, in invoke
    return callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/click/decorators.py", line 46, in new_func
    return f(get_current_context().obj, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/src/blueapi/cli/cli.py", line 245, in wrapper
    raise e
  File "/dls/athena/blueapi/src/blueapi/cli/cli.py", line 235, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/src/blueapi/cli/cli.py", line 471, in env
    status = client.reload_environment(timeout=timeout)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/.venv/lib/python3.11/site-packages/observability_utils/tracing/decorators.py", line 151, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/dls/athena/blueapi/src/blueapi/client/client.py", line 665, in reload_environment
    raise BlueskyRemoteControlError(
blueapi.client.rest.BlueskyRemoteControlError: Failed to tear down the environment

Any chance of handling this error in the same way as the others?

@Alexj9837 Alexj9837 force-pushed the chore/improve-default-error-handling-1379-1409 branch from 7a76c2c to 61e973a Compare April 22, 2026 14:25
Copy link
Copy Markdown
Contributor

@tpoliaw tpoliaw left a comment

Choose a reason for hiding this comment

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

Much better errors for the main error cases, thanks.

Comment thread src/blueapi/client/rest.py Outdated
Comment thread src/blueapi/client/rest.py Outdated
Comment thread src/blueapi/client/rest.py Outdated
Comment thread src/blueapi/client/rest.py Outdated
class BlueskyRequestError(Exception):
def __init__(self, code: int, message: str) -> None:
super().__init__(message, code)
class NotFoundError(BlueskyRequestError):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do some extend BlueskyRequestError and some don't?

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.

The exception that returned (code , message) format inhered it from BlueskyRequestError. I thought it'd look cleaner.

Alexj9837 and others added 3 commits April 22, 2026 17:17
Co-authored-by: Peter Holloway <peter.holloway@diamond.ac.uk>
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.

Improve default error handling Remove stacktrace from error message when not logged into CLI

2 participants