---
title: "Handling Errors"
description: "Handling Errors"
type: "docs"
category: "doc"
tags: []
authors: [Anonymous]
date: "2026-10-10"
last_update: "2026-10-10"
time_minutes: 3
draft: false
unlisted: false
url: "https://www.derafu.dev/docs/core/backbone-bridge-python/errors"
---

# Handling Errors

A failed operation raises `BackboneBridgeError` or one of its subclasses — never a raw `phpy` call failure, and never a PHP exception object:

```python
from derafu_backbone_bridge import MissingParameterError

try:
    dispatcher.dispatch('example_package.example_component.example_worker::sum')
except MissingParameterError as e:
    print(e.php_class)  # "Derafu\BackboneDispatcher\Exception\MissingParameterException"
```

Every `BackboneBridgeError` carries the full `Problem` behind it (in `.problem`), not just a class name and a message:

```python
except MissingParameterError as e:
    e.problem.detail                 # The exception's own message.
    e.problem.instance                # "example_package.example_component.example_worker::sum"
    e.problem.timestamp               # 1755500000.123456 — Unix epoch float, same as `ExecutionMetadata.timestamp`.
    e.problem.throwable.php_class     # Same as `.php_class` below — a read-only shortcut to this.
    e.problem.throwable.file
    e.problem.throwable.line
    e.problem.throwable.trace
    e.metadata                        # ExecutionMetadata of the failed attempt, or `None` — see below.
```

`Problem`/`SafeThrowable` mirror PHP's `ProblemDetailInterface`/`SafeThrowableInterface`, in `snake_case`. Unlike PHP's own `ProblemDetail::toArray()`, `.throwable` here is **always** populated, regardless of whether the underlying `SafeDispatcher` was booted with `debug=True` or `False`: that flag only gates what PHP embeds when *serializing* a problem for an untrusted HTTP consumer, and does not apply to this bridge — `phpy` is an in-process, same-machine, trusted boundary.

`.metadata` is `None` when the failure came from `GenericExplorer` rather than `GenericDispatcher` — `SafeExplorerInterface` does not measure `ExecutionMetadata` (see [Backbone Dispatcher](https://www.derafu.dev/docs/core/backbone-dispatcher/discovery#never-failing-while-exploring-safeexplorer)), so there is honestly none to give in that case; a dispatch failure always has one, and its `.timestamp` is the exact same clock reading as `.problem.timestamp` — not two independent captures.

`.php_class` is a read-only shortcut to `.problem.throwable.php_class` — it exists for backward-compatible ergonomics, not stored data:

```python
from derafu_backbone_bridge import BackboneBridgeError

try:
    dispatcher.dispatch('example_package.example_component.example_worker::fail')
except BackboneBridgeError as e:
    print(e.php_class)  # "RuntimeException" — a plain, unmapped PHP exception.
```

The hierarchy mirrors `derafu/backbone` and `derafu/backbone-dispatcher`'s own exceptions one level deep (`ServiceNotFoundError`/`PackageNotFoundError`/`ComponentNotFoundError`/…, `ResolverError`/`InvalidParameterTypeError`/…), so callers can catch broadly or narrowly exactly as they would in PHP. Anything unmapped still raises `BackboneBridgeError`.

A specific library's own domain exceptions are registered by its own bridge, not by this package:

```python
dispatcher.exceptions.register('App\\Exception\\SomeDomainException', SomeDomainError)
```

Separately, a failure while booting PHP itself (a missing autoloader, a broken dependency, a bootstrap class or method that doesn't exist) raises `BootstrapError` — never a raw `phpy` error either, but also never confused with an operation failure, since booting happens before any `SafeDispatcherInterface` exists to produce a `Problem` from.



---
Last updated on 10/10/2026

