UniteLabs
Guides

Error Handling

Informative error messages and flow control.

Execution Errors

An execution error can be defined or undefined. Depending on the type of execution error, the execution error class inherits from the respective predefined sila error class sila.DefinedExecutionError or sila.UndefinedExecutionError. The description of the execution error is passed via the docstring of the execution error class.

class UnimplementedFeature(sila.DefinedExecutionError):
    """
    The Feature specified by the given Feature identifier is not implemented by the server.
    """

Execution errors that can be raised are passed to the affected SiLA Endpoint using the decorator parameter "errors". A list of defined execution errors is passed.

@sila.UnobservableProperty(errors=[UnimplementedFeature])

Implementation Example

We will define a custom error for a theoretical mechanical failure of the door.

errors.py
class DoorMalfunctionError(sila.DefinedExecutionError):
    """
    A hardware malfunction was detected, and the called door method cannot be completed.
    Please manually check the device and refer to the device manual for reparation instructions.
    """

Code explanation

We create a class called DoorMalfunctionError that inherits from sila.DefinedExecutionError. The docstring contains the information the user receives whenever this error is raised.

has_door_feature.py
from unitelabs.cdk import sila
from .errors import DoorMalfunctionError

class HasDoorController(sila.Feature):
  ...
  @sila.UnobservableCommand(errors=[DoorMalfunctionError])
  async def close_door(self) -> None:
    ...
We then pass the error into any methods which raise the error to define the expected errors for the SiLA client.

Warning The current implementation expects errors to be passed an Exception class rather than an Exception instance, meaning that subclasses of the sila.DefinedExecutionError which add, for example, a more informative description to the instance, will not have access to that information at the time of exception resolution for the client.
class CustomException(sila.DefinedExecutionError):
    """A custom exception."""
    def __init__(self, description, **kwargs):
        kwargs["description"] = description
        super().__init__(self, **kwargs)

@sila.UnobservableCommand(errors=[CustomException("my_method exception.")])  # linter unhappy
async def my_method(self) -> None:
    ...
This pattern would result not only in linting issues as the expected type is incorrect, but would also not provide the additional information to the user via the Client. The client will in this case see "A custom exception." rather than "my_method exception."

Copyright © 2025