D-Bus Error Handling

D-Bus Error Handling

All facilities that return errors from remote methods (such as g_dbus_connection_call_sync()) use GError to represent both D-Bus errors (e.g. errors returned from the other peer) and locally in-process generated errors.

To check if a returned GError is an error from a remote peer, use g_dbus_error_is_remote_error(). To get the actual D-Bus error name, use g_dbus_error_get_remote_error(). Before presenting an error, always use g_dbus_error_strip_remote_error().

In addition, facilities used to return errors to a remote peer also use GError. See g_dbus_method_invocation_return_error() for discussion about how the D-Bus error name is set.

Applications can associate a GError error domain with a set of D-Bus errors in order to automatically map from D-Bus errors to GError and back. This is typically done in the function returning the GQuark for the error domain:

// foo-bar-error.h:

#define FOO_BAR_ERROR (foo_bar_error_quark ())
GQuark foo_bar_error_quark (void);

typedef enum
{
  FOO_BAR_ERROR_FAILED,
  FOO_BAR_ERROR_ANOTHER_ERROR,
  FOO_BAR_ERROR_SOME_THIRD_ERROR,
  FOO_BAR_N_ERRORS / *< skip >* /
} FooBarError;

// foo-bar-error.c:

static const GDBusErrorEntry foo_bar_error_entries[] =
{
  {FOO_BAR_ERROR_FAILED,           "org.project.Foo.Bar.Error.Failed"},
  {FOO_BAR_ERROR_ANOTHER_ERROR,    "org.project.Foo.Bar.Error.AnotherError"},
  {FOO_BAR_ERROR_SOME_THIRD_ERROR, "org.project.Foo.Bar.Error.SomeThirdError"},
};

// Ensure that every error code has an associated D-Bus error name
G_STATIC_ASSERT (G_N_ELEMENTS (foo_bar_error_entries) == FOO_BAR_N_ERRORS);

GQuark
foo_bar_error_quark (void)
{
  static gsize quark = 0;
  g_dbus_error_register_error_domain ("foo-bar-error-quark",
                                      &quark,
                                      foo_bar_error_entries,
                                      G_N_ELEMENTS (foo_bar_error_entries));
  return (GQuark) quark;
}

With this setup, a D-Bus peer can transparently pass e.g. FOO_BAR_ERROR_ANOTHER_ERROR and other peers will see the D-Bus error name org.project.Foo.Bar.Error.AnotherError.

If the other peer is using GDBus, and has registered the association with g_dbus_error_register_error_domain() in advance (e.g. by invoking the FOO_BAR_ERROR quark generation itself in the previous example) the peer will see also FOO_BAR_ERROR_ANOTHER_ERROR instead of G_IO_ERROR_DBUS_ERROR. Note that GDBus clients can still recover org.project.Foo.Bar.Error.AnotherError using g_dbus_error_get_remote_error().

Note that the G_DBUS_ERROR error domain is intended only for returning errors from a remote message bus process. Errors generated locally in-process by e.g. GDBusConnection should use the G_IO_ERROR domain.