## GDBusError GDBusError — Mapping D-Bus errors to and from GError |

## Synopsis

    #include <gio/gio.h>

    enum                GDBusError;
    #define             G_DBUS_ERROR
    gboolean            g_dbus_error_is_remote_error        (const GError *error);
    gchar *             g_dbus_error_get_remote_error       (const GError *error);
    gboolean            g_dbus_error_strip_remote_error     (GError *error);
                        GDBusErrorEntry;
    void                g_dbus_error_register_error_domain  (const gchar *error_domain_quark_name,
                                                             volatile gsize *quark_volatile,
                                                             const GDBusErrorEntry *entries,
                                                             guint num_entries);
    gboolean            g_dbus_error_register_error         (GQuark error_domain,
                                                             gint error_code,
                                                             const gchar *dbus_error_name);
    gboolean            g_dbus_error_unregister_error       (GQuark error_domain,
                                                             gint error_code,
                                                             const gchar *dbus_error_name);
    GError *            g_dbus_error_new_for_dbus_error     (const gchar *dbus_error_name,
                                                             const gchar *dbus_error_message);
    void                g_dbus_error_set_dbus_error         (GError **error,
                                                             const gchar *dbus_error_name,
                                                             const gchar *dbus_error_message,
                                                             const gchar *format,
                                                             ...);
    void                g_dbus_error_set_dbus_error_valist  (GError **error,
                                                             const gchar *dbus_error_name,
                                                             const gchar *dbus_error_message,
                                                             const gchar *format,
                                                             va_list var_args);
    gchar *             g_dbus_error_encode_gerror          (const GError *error);

## Description

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:

Example 1. Error Registration

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    /* 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 volatile gsize quark_volatile = 0;
      g_dbus_error_register_error_domain ("foo-bar-error-quark",
                                          &quark_volatile,
                                          foo_bar_error_entries,
                                          G_N_ELEMENTS (foo_bar_error_entries));
      return (GQuark) quark_volatile;
    }

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 errors in 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 is from the `G_IO_ERROR` domain.

## Details

### enum GDBusError

    typedef enum {
      /* Well-known errors in the org.freedesktop.DBus.Error namespace */
      G_DBUS_ERROR_FAILED,                           /* org.freedesktop.DBus.Error.Failed */
      G_DBUS_ERROR_NO_MEMORY,                        /* org.freedesktop.DBus.Error.NoMemory */
      G_DBUS_ERROR_SERVICE_UNKNOWN,                  /* org.freedesktop.DBus.Error.ServiceUnknown */
      G_DBUS_ERROR_NAME_HAS_NO_OWNER,                /* org.freedesktop.DBus.Error.NameHasNoOwner */
      G_DBUS_ERROR_NO_REPLY,                         /* org.freedesktop.DBus.Error.NoReply */
      G_DBUS_ERROR_IO_ERROR,                         /* org.freedesktop.DBus.Error.IOError */
      G_DBUS_ERROR_BAD_ADDRESS,                      /* org.freedesktop.DBus.Error.BadAddress */
      G_DBUS_ERROR_NOT_SUPPORTED,                    /* org.freedesktop.DBus.Error.NotSupported */
      G_DBUS_ERROR_LIMITS_EXCEEDED,                  /* org.freedesktop.DBus.Error.LimitsExceeded */
      G_DBUS_ERROR_ACCESS_DENIED,                    /* org.freedesktop.DBus.Error.AccessDenied */
      G_DBUS_ERROR_AUTH_FAILED,                      /* org.freedesktop.DBus.Error.AuthFailed */
      G_DBUS_ERROR_NO_SERVER,                        /* org.freedesktop.DBus.Error.NoServer */
      G_DBUS_ERROR_TIMEOUT,                          /* org.freedesktop.DBus.Error.Timeout */
      G_DBUS_ERROR_NO_NETWORK,                       /* org.freedesktop.DBus.Error.NoNetwork */
      G_DBUS_ERROR_ADDRESS_IN_USE,                   /* org.freedesktop.DBus.Error.AddressInUse */
      G_DBUS_ERROR_DISCONNECTED,                     /* org.freedesktop.DBus.Error.Disconnected */
      G_DBUS_ERROR_INVALID_ARGS,                     /* org.freedesktop.DBus.Error.InvalidArgs */
      G_DBUS_ERROR_FILE_NOT_FOUND,                   /* org.freedesktop.DBus.Error.FileNotFound */
      G_DBUS_ERROR_FILE_EXISTS,                      /* org.freedesktop.DBus.Error.FileExists */
      G_DBUS_ERROR_UNKNOWN_METHOD,                   /* org.freedesktop.DBus.Error.UnknownMethod */
      G_DBUS_ERROR_TIMED_OUT,                        /* org.freedesktop.DBus.Error.TimedOut */
      G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,             /* org.freedesktop.DBus.Error.MatchRuleNotFound */
      G_DBUS_ERROR_MATCH_RULE_INVALID,               /* org.freedesktop.DBus.Error.MatchRuleInvalid */
      G_DBUS_ERROR_SPAWN_EXEC_FAILED,                /* org.freedesktop.DBus.Error.Spawn.ExecFailed */
      G_DBUS_ERROR_SPAWN_FORK_FAILED,                /* org.freedesktop.DBus.Error.Spawn.ForkFailed */
      G_DBUS_ERROR_SPAWN_CHILD_EXITED,               /* org.freedesktop.DBus.Error.Spawn.ChildExited */
      G_DBUS_ERROR_SPAWN_CHILD_SIGNALED,             /* org.freedesktop.DBus.Error.Spawn.ChildSignaled */
      G_DBUS_ERROR_SPAWN_FAILED,                     /* org.freedesktop.DBus.Error.Spawn.Failed */
      G_DBUS_ERROR_SPAWN_SETUP_FAILED,               /* org.freedesktop.DBus.Error.Spawn.FailedToSetup */
      G_DBUS_ERROR_SPAWN_CONFIG_INVALID,             /* org.freedesktop.DBus.Error.Spawn.ConfigInvalid */
      G_DBUS_ERROR_SPAWN_SERVICE_INVALID,            /* org.freedesktop.DBus.Error.Spawn.ServiceNotValid */
      G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,          /* org.freedesktop.DBus.Error.Spawn.ServiceNotFound */
      G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,        /* org.freedesktop.DBus.Error.Spawn.PermissionsInvalid */
      G_DBUS_ERROR_SPAWN_FILE_INVALID,               /* org.freedesktop.DBus.Error.Spawn.FileInvalid */
      G_DBUS_ERROR_SPAWN_NO_MEMORY,                  /* org.freedesktop.DBus.Error.Spawn.NoMemory */
      G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,          /* org.freedesktop.DBus.Error.UnixProcessIdUnknown */
      G_DBUS_ERROR_INVALID_SIGNATURE,                /* org.freedesktop.DBus.Error.InvalidSignature */
      G_DBUS_ERROR_INVALID_FILE_CONTENT,             /* org.freedesktop.DBus.Error.InvalidFileContent */
      G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN, /* org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown */
      G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,           /* org.freedesktop.DBus.Error.AdtAuditDataUnknown */
      G_DBUS_ERROR_OBJECT_PATH_IN_USE                /* org.freedesktop.DBus.Error.ObjectPathInUse */
    } GDBusError;

Error codes for the `G_DBUS_ERROR` error domain.

`G_DBUS_ERROR_FAILED` | A generic error; "something went wrong" - see the error message for more.
`G_DBUS_ERROR_NO_MEMORY` | There was not enough memory to complete an operation.
`G_DBUS_ERROR_SERVICE_UNKNOWN` | The bus doesn't know how to launch a service to supply the bus name you wanted.
`G_DBUS_ERROR_NAME_HAS_NO_OWNER` | The bus name you referenced doesn't exist (i.e. no application owns it).
`G_DBUS_ERROR_NO_REPLY` | No reply to a message expecting one, usually means a timeout occurred.
`G_DBUS_ERROR_IO_ERROR` | Something went wrong reading or writing to a socket, for example.
`G_DBUS_ERROR_BAD_ADDRESS` | A D-Bus bus address was malformed.
`G_DBUS_ERROR_NOT_SUPPORTED` | Requested operation isn't supported (like ENOSYS on UNIX).
`G_DBUS_ERROR_LIMITS_EXCEEDED` | Some limited resource is exhausted.
`G_DBUS_ERROR_ACCESS_DENIED` | Security restrictions don't allow doing what you're trying to do.
`G_DBUS_ERROR_AUTH_FAILED` | Authentication didn't work.
`G_DBUS_ERROR_NO_SERVER` | Unable to connect to server (probably caused by ECONNREFUSED on a socket).
`G_DBUS_ERROR_TIMEOUT` | Certain timeout errors, possibly ETIMEDOUT on a socket. Note that `G_DBUS_ERROR_NO_REPLY` is used for message reply timeouts. Warning: this is confusingly-named given that `G_DBUS_ERROR_TIMED_OUT` also exists. We can't fix it for compatibility reasons so just be careful.
`G_DBUS_ERROR_NO_NETWORK` | No network access (probably ENETUNREACH on a socket).
`G_DBUS_ERROR_ADDRESS_IN_USE` | Can't bind a socket since its address is in use (i.e. EADDRINUSE).
`G_DBUS_ERROR_DISCONNECTED` | The connection is disconnected and you're trying to use it.
`G_DBUS_ERROR_INVALID_ARGS` | Invalid arguments passed to a method call.
`G_DBUS_ERROR_FILE_NOT_FOUND` | Missing file.
`G_DBUS_ERROR_FILE_EXISTS` | Existing file and the operation you're using does not silently overwrite.
`G_DBUS_ERROR_UNKNOWN_METHOD` | Method name you invoked isn't known by the object you invoked it on.
`G_DBUS_ERROR_TIMED_OUT` | Certain timeout errors, e.g. while starting a service. Warning: this is confusingly-named given that `G_DBUS_ERROR_TIMEOUT` also exists. We can't fix it for compatibility reasons so just be careful.
`G_DBUS_ERROR_MATCH_RULE_NOT_FOUND` | Tried to remove or modify a match rule that didn't exist.
`G_DBUS_ERROR_MATCH_RULE_INVALID` | The match rule isn't syntactically valid.
`G_DBUS_ERROR_SPAWN_EXEC_FAILED` | While starting a new process, the `exec()` call failed.
`G_DBUS_ERROR_SPAWN_FORK_FAILED` | While starting a new process, the `fork()` call failed.
`G_DBUS_ERROR_SPAWN_CHILD_EXITED` | While starting a new process, the child exited with a status code.
`G_DBUS_ERROR_SPAWN_CHILD_SIGNALED` | While starting a new process, the child exited on a signal.
`G_DBUS_ERROR_SPAWN_FAILED` | While starting a new process, something went wrong.
`G_DBUS_ERROR_SPAWN_SETUP_FAILED` | We failed to setup the environment correctly.
`G_DBUS_ERROR_SPAWN_CONFIG_INVALID` | We failed to setup the config parser correctly.
`G_DBUS_ERROR_SPAWN_SERVICE_INVALID` | Bus name was not valid.
`G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND` | Service file not found in system-services directory.
`G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID` | Permissions are incorrect on the setuid helper.
`G_DBUS_ERROR_SPAWN_FILE_INVALID` | Service file invalid (Name, User or Exec missing).
`G_DBUS_ERROR_SPAWN_NO_MEMORY` | Tried to get a UNIX process ID and it wasn't available.
`G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN` | Tried to get a UNIX process ID and it wasn't available.
`G_DBUS_ERROR_INVALID_SIGNATURE` | A type signature is not valid.
`G_DBUS_ERROR_INVALID_FILE_CONTENT` | A file contains invalid syntax or is otherwise broken.
`G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN` | Asked for SELinux security context and it wasn't available.
`G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN` | Asked for ADT audit data and it wasn't available.
`G_DBUS_ERROR_OBJECT_PATH_IN_USE` | There's already an object with the requested object path.

Since 2.26

### G_DBUS_ERROR

    #define G_DBUS_ERROR g_dbus_error_quark()

Error domain for errors generated by a remote message bus. Errors in this domain will be from the GDBusError enumeration. See GError for more information on error domains.

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

Since 2.26

### g_dbus_error_is_remote_error ()

    gboolean            g_dbus_error_is_remote_error        (const GError *error);

Checks if `error` represents an error received via D-Bus from a remote peer. If so, use `g_dbus_error_get_remote_error()` to get the name of the error.

`error` : | A GError.
Returns : | `TRUE` if `error` represents an error from a remote peer, `FALSE` otherwise.

Since 2.26

### g_dbus_error_get_remote_error ()

    gchar *             g_dbus_error_get_remote_error       (const GError *error);

Gets the D-Bus error name used for `error`, if any.

This function is guaranteed to return a D-Bus error name for all GErrors returned from functions handling remote method calls (e.g. `g_dbus_connection_call_finish()`) unless `g_dbus_error_strip_remote_error()` has been used on `error`.

`error` : | A GError.
Returns : | An allocated string or `NULL` if the D-Bus error name could not be found. Free with `g_free()`.

Since 2.26

### g_dbus_error_strip_remote_error ()

    gboolean            g_dbus_error_strip_remote_error     (GError *error);

Looks for extra information in the error message used to recover the D-Bus error name and strips it if found. If stripped, the message field in `error` will correspond exactly to what was received on the wire.

This is typically used when presenting errors to the end user.

`error` : | A GError.
Returns : | `TRUE` if information was stripped, `FALSE` otherwise.

Since 2.26

### GDBusErrorEntry

    typedef struct {
      gint         error_code;
      const gchar *dbus_error_name;
    } GDBusErrorEntry;

Struct used in `g_dbus_error_register_error_domain()`.

gint `error_code`; | An error code.
const gchar *`dbus_error_name`; | The D-Bus error name to associate with `error_code`.

Since 2.26

### g_dbus_error_register_error_domain ()

    void                g_dbus_error_register_error_domain  (const gchar *error_domain_quark_name,
                                                             volatile gsize *quark_volatile,
                                                             const GDBusErrorEntry *entries,
                                                             guint num_entries);

Helper function for associating a GError error domain with D-Bus error names.

`error_domain_quark_name` : | The error domain name.
`quark_volatile` : | A pointer where to store the GQuark.
`entries` : | A pointer to `num_entries` GDBusErrorEntry struct items.
`num_entries` : | Number of items to register.

Since 2.26

### g_dbus_error_register_error ()

    gboolean            g_dbus_error_register_error         (GQuark error_domain,
                                                             gint error_code,
                                                             const gchar *dbus_error_name);

Creates an association to map between `dbus_error_name` and GErrors specified by `error_domain` and `error_code`.

This is typically done in the routine that returns the GQuark for an error domain.

`error_domain` : | A GQuark for a error domain.
`error_code` : | An error code.
`dbus_error_name` : | A D-Bus error name.
Returns : | `TRUE` if the association was created, `FALSE` if it already exists.

Since 2.26

### g_dbus_error_unregister_error ()

    gboolean            g_dbus_error_unregister_error       (GQuark error_domain,
                                                             gint error_code,
                                                             const gchar *dbus_error_name);

Destroys an association previously set up with `g_dbus_error_register_error()`.

`error_domain` : | A GQuark for a error domain.
`error_code` : | An error code.
`dbus_error_name` : | A D-Bus error name.
Returns : | `TRUE` if the association was destroyed, `FALSE` if it wasn't found.

Since 2.26

### g_dbus_error_new_for_dbus_error ()

    GError *            g_dbus_error_new_for_dbus_error     (const gchar *dbus_error_name,
                                                             const gchar *dbus_error_message);

Creates a GError based on the contents of `dbus_error_name` and `dbus_error_message`.

Errors registered with `g_dbus_error_register_error()` will be looked up using `dbus_error_name` and if a match is found, the error domain and code is used. Applications can use `g_dbus_error_get_remote_error()` to recover `dbus_error_name`.

If a match against a registered error is not found and the D-Bus error name is in a form as returned by `g_dbus_error_encode_gerror()` the error domain and code encoded in the name is used to create the GError. Also, `dbus_error_name` is added to the error message such that it can be recovered with `g_dbus_error_get_remote_error()`.

Otherwise, a GError with the error code `G_IO_ERROR_DBUS_ERROR` in the G_IO_ERROR error domain is returned. Also, `dbus_error_name` is added to the error message such that it can be recovered with `g_dbus_error_get_remote_error()`.

In all three cases, `dbus_error_name` can always be recovered from the returned GError using the `g_dbus_error_get_remote_error()` function (unless `g_dbus_error_strip_remote_error()` hasn't been used on the returned error).

This function is typically only used in object mappings to prepare GError instances for applications. Regular applications should not use it.

`dbus_error_name` : | D-Bus error name.
`dbus_error_message` : | D-Bus error message.
Returns : | An allocated GError. Free with `g_error_free()`.

Since 2.26

### g_dbus_error_set_dbus_error ()

    void                g_dbus_error_set_dbus_error         (GError **error,
                                                             const gchar *dbus_error_name,
                                                             const gchar *dbus_error_message,
                                                             const gchar *format,
                                                             ...);

Does nothing if `error` is `NULL`. Otherwise sets *`error` to a new GError created with `g_dbus_error_new_for_dbus_error()` with `dbus_error_message` prepend with `format` (unless `NULL`).

`error` : | A pointer to a GError or `NULL`.
`dbus_error_name` : | D-Bus error name.
`dbus_error_message` : | D-Bus error message.
`format` : | `printf()`-style format to prepend to `dbus_error_message` or `NULL`. [allow-none]
`...` : | Arguments for `format`.

Since 2.26

### g_dbus_error_set_dbus_error_valist ()

    void                g_dbus_error_set_dbus_error_valist  (GError **error,
                                                             const gchar *dbus_error_name,
                                                             const gchar *dbus_error_message,
                                                             const gchar *format,
                                                             va_list var_args);

Like `g_dbus_error_set_dbus_error()` but intended for language bindings.

`error` : | A pointer to a GError or `NULL`.
`dbus_error_name` : | D-Bus error name.
`dbus_error_message` : | D-Bus error message.
`format` : | `printf()`-style format to prepend to `dbus_error_message` or `NULL`. [allow-none]
`var_args` : | Arguments for `format`.

Since 2.26

### g_dbus_error_encode_gerror ()

    gchar *             g_dbus_error_encode_gerror          (const GError *error);

Creates a D-Bus error name to use for `error`. If `error` matches a registered error (cf. `g_dbus_error_register_error()`), the corresponding D-Bus error name will be returned.

Otherwise the a name of the form `org.gtk.GDBus.UnmappedGError.Quark._ESCAPED_QUARK_NAME.Code_ERROR_CODE` will be used. This allows other GDBus applications to map the error on the wire back to a GError using `g_dbus_error_new_for_dbus_error()`.

This function is typically only used in object mappings to put a GError on the wire. Regular applications should not use it.

`error` : | A GError.
Returns : | A D-Bus error name (never `NULL`). Free with `g_free()`.

Since 2.26