There is a lot of exactly same code. Maybe move it to method like:
```
void send_dbus_error(type? conn, const char *type)
{
  DBus::MessageError reply(msg, type, DBUS_ERROR_FAILED);
  conn.send(reply);
}
```
and then you can have easier code in handling
```
 catch (const InvalidGroupException& e)
 {
   send_dbus_error(conn, "error.invalid_group")
 }
```

but even much nicer solution that allows easier future extension is to have one ancestor like you have `SnapperException` with method `dbus_error_type` and then you can reduce this mega catch to one catch
```
catch (const SnapperException& e)
{
  DBus::MessageError reply(msg, e.dbus_error_type, DBUS_ERROR_FAILED);
  conn.send(reply);
}
```
Usually when you have really big conditions it indicate that polymorphism can be good solution.