Skip to content

Conversation

@gpauloski
Copy link
Collaborator

Description

Previously, errors during the resolve of a proxy looked odd due to the exception handling, resulting in errors starting with this:

  File "/Users/jgpaul/workspace/proxystore/venv/lib/python3.13/site-packages/proxystore/proxy/__init__.py", line 283, in __proxy_wrapped__
    return cast(T, object.__getattribute__(self, '__proxy_target__'))
                   ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Proxy' object has no attribute '__proxy_target__'

During handling of the above exception, another exception occurred
....

For example, run this:

from proxystore.connectors.local import LocalConnector
from proxystore.store import Store

with Store('proxy-future-example', LocalConnector()) as store:
    key = store.put([1, 2, 3])
    proxy = store.proxy_from_key(key)
    store.evict(key)
    len(proxy)

And you get the following error that starts in a very cryptic manner with object attribute errors.

Traceback (most recent call last):
  File "/Users/jgpaul/workspace/academy/venv/lib/python3.13/site-packages/proxystore/proxy/__init__.py", line 283, in __proxy_wrapped__
    return cast(T, object.__getattribute__(self, '__proxy_target__'))
                   ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Proxy' object has no attribute '__proxy_target__'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/jgpaul/workspace/academy/t.py", line 8, in <module>
    len(proxy)
    ~~~^^^^^^^
  File "/Users/jgpaul/workspace/academy/venv/lib/python3.13/site-packages/proxystore/proxy/__init__.py", line 577, in __len__
    return len(self.__proxy_wrapped__)  # type: ignore[arg-type]
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jgpaul/workspace/academy/venv/lib/python3.13/site-packages/proxystore/proxy/__init__.py", line 291, in __proxy_wrapped__
    target = factory()
  File "/Users/jgpaul/workspace/academy/venv/lib/python3.13/site-packages/proxystore/store/factory.py", line 79, in __call__
    obj = self.resolve()
  File "/Users/jgpaul/workspace/academy/venv/lib/python3.13/site-packages/proxystore/store/factory.py", line 119, in resolve
    raise ProxyResolveMissingKeyError(
    ...<3 lines>...
    )
proxystore.store.exceptions.ProxyResolveMissingKeyError: Proxy cannot resolve target object with key='LocalKey(id='89a42e28-b70e-48da-b13a-1025ff28199d')' from Store(name='proxy-future-example'): store returned NoneType with key.

Now, the error handling is improved to raise a standardized ProxyResolveError which is raised from the underlying exception from the factory.

Traceback (most recent call last):
  File "/Users/jgpaul/workspace/proxystore/proxystore/proxy/__init__.py", line 310, in __proxy_wrapped__
    target = factory()
             ^^^^^^^^^
  File "/Users/jgpaul/workspace/proxystore/proxystore/store/factory.py", line 79, in __call__
    obj = self.resolve()
          ^^^^^^^^^^^^^^
  File "/Users/jgpaul/workspace/proxystore/proxystore/store/factory.py", line 119, in resolve
    raise ProxyResolveMissingKeyError(
proxystore.store.exceptions.ProxyResolveMissingKeyError: Cannot resolve target object with key='LocalKey(id='36882d49-9915-46a3-9649-80d52a42f771')' from Store(name='proxy-future-example') because there is no object associated with the key. This can often occur when the target object is evicted from the store while proxies of the target still exist.

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

Traceback (most recent call last):
  File "/Users/jgpaul/workspace/proxystore/t.py", line 8, in <module>
    len(proxy)
  File "/Users/jgpaul/workspace/proxystore/proxystore/proxy/__init__.py", line 604, in __len__
    return len(self.__proxy_wrapped__)  # type: ignore[arg-type]
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/jgpaul/workspace/proxystore/proxystore/proxy/__init__.py", line 312, in __proxy_wrapped__
    raise ProxyResolveError(
proxystore.proxy.ProxyResolveError: The factory of this proxy raised an error while resolving the target object. See the full stack trace for the direct cause of this exception.

I'm classifying this as a breaking change because the error return types will change for users, but the return type of the resolve errors was never defined anywhere.

Fixes N/A

Type of Change

  • Breaking Change (fix or enhancement which changes existing semantics of the public interface)
  • Enhancement (new features or improvements to existing functionality)
  • Bug (fixes for a bug or issue)
  • Internal (refactoring, style changes, testing, optimizations)
  • Documentation update (changes to documentation or examples)
  • Package (dependencies, versions, package metadata)
  • Development (CI workflows, pre-commit, linters, templates)
  • Security (security related changes)

Testing

Updated tests.

Pull Request Checklist

Please confirm the PR meets the following requirements.

  • Tags added to PR (e.g., breaking, bug, enhancement, internal, documentation, package, development, security).
  • Code changes pass pre-commit (e.g., mypy, ruff, etc.).
  • Tests have been added to show the fix is effective or that the new feature works.
  • New and existing unit tests pass locally with the changes.
  • Docs have been updated and reviewed if relevant.

@gpauloski gpauloski added enhancement New features or improvements to existing functionality breaking Backwards incompatible change to public interfaces labels Jun 12, 2025
The stack trace of an exception raised in the factory of a proxy when
resolved is often confusing because it starts with "AttributeError:
'Proxy' object has no attribute '__proxy_target__'" and then the true
error is raised in the handling of the above error. This commit changes
the behavior to raise a ProxyResolveError which is raised from the error
caught from the factory call.
@gpauloski gpauloski force-pushed the proxy-resolve-error-clarity branch from ef140c1 to 85aac1c Compare June 13, 2025 03:08
@gpauloski gpauloski merged commit bea96dd into main Jun 13, 2025
12 checks passed
@gpauloski gpauloski deleted the proxy-resolve-error-clarity branch June 13, 2025 03:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Backwards incompatible change to public interfaces enhancement New features or improvements to existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants