Patchwork [09/14] qerror: qerror_report(): take an index and a human error message

login
register
mail settings
Submitter Luiz Capitulino
Date July 25, 2012, 8:50 p.m.
Message ID <1343249431-9245-10-git-send-email-lcapitulino@redhat.com>
Download mbox | patch
Permalink /patch/173265/
State New
Headers show

Comments

Luiz Capitulino - July 25, 2012, 8:50 p.m.
This commit does three indivisible changes:

1. qerror_report() is changed to take an index to error_object_table[]
   and a human error message in printf format.

   That is, we go from:

        qerror_report(const char *fmt, ...);

        where fmt is a json dict in string format and the arguments
        are error data (the data member in qapi-schema-error.json).

    To:

        qerror_report(int err_class, const char *fmt, ...);

        where err_class is the error_object_table[] index, and the
        remaining arguments form a printf-like string, which is going
        to be used as the human error message.

    Future commits will turn the index into a proper enumeration.

    qerror_report() is also changed to use build_error_dict(), which
    was introduced by the last commit.

2. error_object_from_fmt(), which was used to build the error object
   from the previous 'fmt' argument is dropped

3. All calls to qerror_report() are changed to adhere to the new
   signature. As an example, a call like:

        qerror_report(QERR_DEVICE_IN_USE, device);

    is changed to:

         qerror_report(/* QERR_DEVICE_IN_USE */ 14,
                        "Device 'device=%s' is in use", device);

    The name in the comment is going to be the future enum for the
    index used.

TODO: fix long lines.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 block/cow.c       |  3 +--
 block/qcow.c      |  3 +--
 block/qcow2.c     |  3 +--
 block/qed.c       |  3 +--
 blockdev.c        | 10 ++++----
 hw/pci.c          |  4 +--
 hw/qdev-monitor.c | 24 +++++++++---------
 hw/usb/bus.c      |  3 +--
 hw/usb/hcd-ehci.c |  6 ++---
 hw/usb/redirect.c |  5 ++--
 monitor.c         | 55 ++++++++++++++++++-----------------------
 qemu-option.c     |  2 +-
 qerror.c          | 73 ++++++-------------------------------------------------
 qerror.h          |  2 +-
 14 files changed, 60 insertions(+), 136 deletions(-)

Patch

diff --git a/block/cow.c b/block/cow.c
index a5a00eb..002dcf1 100644
--- a/block/cow.c
+++ b/block/cow.c
@@ -81,8 +81,7 @@  static int cow_open(BlockDriverState *bs, int flags)
         char version[64];
         snprintf(version, sizeof(version),
                "COW version %d", cow_header.version);
-        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-            bs->device_name, "cow", version);
+        qerror_report(/* QERR_UNKNOWN_BLOCK_FORMAT_FEATURE */ 67, "'device=%s' uses a format=%s feature which is not supported by this qemu version: feature=%s", bs->device_name, "cow", version);
         ret = -ENOTSUP;
         goto fail;
     }
diff --git a/block/qcow.c b/block/qcow.c
index 7b5ab87..e820099 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -118,8 +118,7 @@  static int qcow_open(BlockDriverState *bs, int flags)
     if (header.version != QCOW_VERSION) {
         char version[64];
         snprintf(version, sizeof(version), "QCOW version %d", header.version);
-        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-            bs->device_name, "qcow", version);
+        qerror_report(/* QERR_UNKNOWN_BLOCK_FORMAT_FEATURE */ 67, "'device=%s' uses a format=%s feature which is not supported by this qemu version: feature=%s", bs->device_name, "qcow", version);
         ret = -ENOTSUP;
         goto fail;
     }
diff --git a/block/qcow2.c b/block/qcow2.c
index 870148d..a5b46df 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -192,8 +192,7 @@  static void GCC_FMT_ATTR(2, 3) report_unsupported(BlockDriverState *bs,
     vsnprintf(msg, sizeof(msg), fmt, ap);
     va_end(ap);
 
-    qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-        bs->device_name, "qcow2", msg);
+    qerror_report(/* QERR_UNKNOWN_BLOCK_FORMAT_FEATURE */ 67, "'device=%s' uses a format=%s feature which is not supported by this qemu version: feature=%s", bs->device_name, "qcow2", msg);
 }
 
 static void report_unsupported_feature(BlockDriverState *bs,
diff --git a/block/qed.c b/block/qed.c
index 5f3eefa..fda3dcc 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -397,8 +397,7 @@  static int bdrv_qed_open(BlockDriverState *bs, int flags)
         char buf[64];
         snprintf(buf, sizeof(buf), "%" PRIx64,
             s->header.features & ~QED_FEATURE_MASK);
-        qerror_report(QERR_UNKNOWN_BLOCK_FORMAT_FEATURE,
-            bs->device_name, "QED", buf);
+        qerror_report(/* QERR_UNKNOWN_BLOCK_FORMAT_FEATURE */ 67, "'device=%s' uses a format=%s feature which is not supported by this qemu version: feature=%s", bs->device_name, "QED", buf);
         return -ENOTSUP;
     }
     if (!qed_is_cluster_size_valid(s->header.cluster_size)) {
diff --git a/blockdev.c b/blockdev.c
index 3d75015..6060c88 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -633,18 +633,18 @@  void do_commit(Monitor *mon, const QDict *qdict)
     if (!strcmp(device, "all")) {
         ret = bdrv_commit_all();
         if (ret == -EBUSY) {
-            qerror_report(QERR_DEVICE_IN_USE, device);
+            qerror_report(/* QERR_DEVICE_IN_USE */ 14, "Device 'device=%s' is in use", device);
             return;
         }
     } else {
         bs = bdrv_find(device);
         if (!bs) {
-            qerror_report(QERR_DEVICE_NOT_FOUND, device);
+            qerror_report(/* QERR_DEVICE_NOT_FOUND */ 22, "Device 'device=%s' not found", device);
             return;
         }
         ret = bdrv_commit(bs);
         if (ret == -EBUSY) {
-            qerror_report(QERR_DEVICE_IN_USE, device);
+            qerror_report(/* QERR_DEVICE_IN_USE */ 14, "Device 'device=%s' is in use", device);
             return;
         }
     }
@@ -985,11 +985,11 @@  int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
 
     bs = bdrv_find(id);
     if (!bs) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, id);
+        qerror_report(/* QERR_DEVICE_NOT_FOUND */ 22, "Device 'device=%s' not found", id);
         return -1;
     }
     if (bdrv_in_use(bs)) {
-        qerror_report(QERR_DEVICE_IN_USE, id);
+        qerror_report(/* QERR_DEVICE_IN_USE */ 14, "Device 'device=%s' is in use", id);
         return -1;
     }
 
diff --git a/hw/pci.c b/hw/pci.c
index 99a4304..1aac667 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1506,7 +1506,7 @@  static int pci_qdev_init(DeviceState *qdev)
     if (pci_dev == NULL)
         return -1;
     if (qdev->hotplugged && pc->no_hotplug) {
-        qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev)));
+        qerror_report(/* QERR_DEVICE_NO_HOTPLUG */ 19, "Device 'device=%s' does not support hotplugging", object_get_typename(OBJECT(pci_dev)));
         do_pci_unregister_device(pci_dev);
         return -1;
     }
@@ -1547,7 +1547,7 @@  static int pci_unplug_device(DeviceState *qdev)
     PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
 
     if (pc->no_hotplug) {
-        qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev)));
+        qerror_report(/* QERR_DEVICE_NO_HOTPLUG */ 19, "Device 'device=%s' does not support hotplugging", object_get_typename(OBJECT(dev)));
         return -1;
     }
     return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index 7915b45..db2ed77 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -326,7 +326,7 @@  static BusState *qbus_find(const char *path)
         }
         bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
         if (!bus) {
-            qerror_report(QERR_BUS_NOT_FOUND, elem);
+            qerror_report(/* QERR_BUS_NOT_FOUND */ 7, "Bus 'bus=%s' not found", elem);
             return NULL;
         }
         pos = len;
@@ -349,7 +349,7 @@  static BusState *qbus_find(const char *path)
         pos += len;
         dev = qbus_find_dev(bus, elem);
         if (!dev) {
-            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
+            qerror_report(/* QERR_DEVICE_NOT_FOUND */ 22, "Device 'device=%s' not found", elem);
             if (!monitor_cur_is_qmp()) {
                 qbus_list_dev(bus);
             }
@@ -365,12 +365,12 @@  static BusState *qbus_find(const char *path)
              * one child bus accept it nevertheless */
             switch (dev->num_child_bus) {
             case 0:
-                qerror_report(QERR_DEVICE_NO_BUS, elem);
+                qerror_report(/* QERR_DEVICE_NO_BUS */ 18, "Device 'device=%s' has no child bus", elem);
                 return NULL;
             case 1:
                 return QLIST_FIRST(&dev->child_bus);
             default:
-                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
+                qerror_report(/* QERR_DEVICE_MULTIPLE_BUSSES */ 17, "Device 'device=%s' has multiple child busses", elem);
                 if (!monitor_cur_is_qmp()) {
                     qbus_list_bus(dev);
                 }
@@ -386,7 +386,7 @@  static BusState *qbus_find(const char *path)
         pos += len;
         bus = qbus_find_bus(dev, elem);
         if (!bus) {
-            qerror_report(QERR_BUS_NOT_FOUND, elem);
+            qerror_report(/* QERR_BUS_NOT_FOUND */ 7, "Bus 'bus=%s' not found", elem);
             if (!monitor_cur_is_qmp()) {
                 qbus_list_bus(dev);
             }
@@ -405,7 +405,7 @@  DeviceState *qdev_device_add(QemuOpts *opts)
 
     driver = qemu_opt_get(opts, "driver");
     if (!driver) {
-        qerror_report(QERR_MISSING_PARAMETER, "driver");
+        qerror_report(/* QERR_MISSING_PARAMETER */ 42, "Parameter 'name=%s' is missing", "driver");
         return NULL;
     }
 
@@ -421,7 +421,7 @@  DeviceState *qdev_device_add(QemuOpts *opts)
     }
 
     if (!obj) {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
+        qerror_report(/* QERR_INVALID_PARAMETER_VALUE */ 33, "Parameter 'name=%s' expects expected=%s", "driver", "device type");
         return NULL;
     }
 
@@ -435,20 +435,18 @@  DeviceState *qdev_device_add(QemuOpts *opts)
             return NULL;
         }
         if (strcmp(object_get_typename(OBJECT(bus)), k->bus_type) != 0) {
-            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
-                          driver, object_get_typename(OBJECT(bus)));
+            qerror_report(/* QERR_BAD_BUS_FOR_DEVICE */ 2, "Device 'device=%s' can't go on a bad_bus_type=%s bus", driver, object_get_typename(OBJECT(bus)));
             return NULL;
         }
     } else {
         bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
         if (!bus) {
-            qerror_report(QERR_NO_BUS_FOR_DEVICE,
-                          driver, k->bus_type);
+            qerror_report(/* QERR_NO_BUS_FOR_DEVICE */ 43, "No 'bus=%s' bus found for device 'device=%s'", driver, k->bus_type);
             return NULL;
         }
     }
     if (qdev_hotplug && !bus->allow_hotplug) {
-        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
+        qerror_report(/* QERR_BUS_NO_HOTPLUG */ 6, "Bus 'bus=%s' does not support hotplugging", bus->name);
         return NULL;
     }
 
@@ -479,7 +477,7 @@  DeviceState *qdev_device_add(QemuOpts *opts)
         g_free(name);
     }        
     if (qdev_init(qdev) < 0) {
-        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
+        qerror_report(/* QERR_DEVICE_INIT_FAILED */ 13, "Device 'device=%s' could not be initialized", driver);
         return NULL;
     }
     qdev->opts = opts;
diff --git a/hw/usb/bus.c b/hw/usb/bus.c
index b649360..28901cb 100644
--- a/hw/usb/bus.c
+++ b/hw/usb/bus.c
@@ -303,8 +303,7 @@  int usb_register_companion(const char *masterbus, USBPort *ports[],
     }
 
     if (!bus || !bus->ops->register_companion) {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
-                      "an USB masterbus");
+        qerror_report(/* QERR_INVALID_PARAMETER_VALUE */ 33, "Parameter 'name=%s' expects expected=%s", "masterbus", "an USB masterbus");
         if (bus) {
             error_printf_unless_qmp(
                 "USB bus '%s' does not allow companion controllers\n",
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index b043e7c..2d42945 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -933,8 +933,7 @@  static int ehci_register_companion(USBBus *bus, USBPort *ports[],
     uint32_t i;
 
     if (firstport + portcount > NB_PORTS) {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, "firstport",
-                      "firstport on masterbus");
+        qerror_report(/* QERR_INVALID_PARAMETER_VALUE */ 33, "Parameter 'name=%s' expects expected=%s", "firstport", "firstport on masterbus");
         error_printf_unless_qmp(
             "firstport value of %u makes companion take ports %u - %u, which "
             "is outside of the valid range of 0 - %u\n", firstport, firstport,
@@ -944,8 +943,7 @@  static int ehci_register_companion(USBBus *bus, USBPort *ports[],
 
     for (i = 0; i < portcount; i++) {
         if (s->companion_ports[firstport + i]) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "masterbus",
-                          "an USB masterbus");
+            qerror_report(/* QERR_INVALID_PARAMETER_VALUE */ 33, "Parameter 'name=%s' expects expected=%s", "masterbus", "an USB masterbus");
             error_printf_unless_qmp(
                 "port %u on masterbus %s already has a companion assigned\n",
                 firstport + i, bus->qbus.name);
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 10b4fbb..d43dae2 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -902,7 +902,7 @@  static int usbredir_initfn(USBDevice *udev)
     int i;
 
     if (dev->cs == NULL) {
-        qerror_report(QERR_MISSING_PARAMETER, "chardev");
+        qerror_report(/* QERR_MISSING_PARAMETER */ 42, "Parameter 'name=%s' is missing", "chardev");
         return -1;
     }
 
@@ -911,8 +911,7 @@  static int usbredir_initfn(USBDevice *udev)
                                            &dev->filter_rules,
                                            &dev->filter_rules_count);
         if (i) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "filter",
-                          "a usb device filter string");
+            qerror_report(/* QERR_INVALID_PARAMETER_VALUE */ 33, "Parameter 'name=%s' expects expected=%s", "filter", "a usb device filter string");
             return -1;
         }
     }
diff --git a/monitor.c b/monitor.c
index c22cfca..0ccca3b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -227,7 +227,7 @@  int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
                           void *opaque)
 {
     if (monitor_ctrl_mode(mon)) {
-        qerror_report(QERR_MISSING_PARAMETER, "password");
+        qerror_report(/* QERR_MISSING_PARAMETER */ 42, "Parameter 'name=%s' is missing", "password");
         return -EINVAL;
     } else if (mon->rs) {
         readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
@@ -936,7 +936,7 @@  static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
         int tls = qdict_get_try_bool(qdict, "tls", 0);
         if (!using_spice) {
             /* correct one? spice isn't a device ,,, */
-            qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
+            qerror_report(/* QERR_DEVICE_NOT_ACTIVE */ 20, "Device 'device=%s' has not been activated", "spice");
             return -1;
         }
         if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
@@ -953,13 +953,13 @@  static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
     } else if ((s = qemu_chr_find(protocol)) != NULL) {
 	int fd = monitor_get_fd(mon, fdname);
 	if (qemu_chr_add_client(s, fd) < 0) {
-	    qerror_report(QERR_ADD_CLIENT_FAILED);
+qerror_report(/* QERR_ADD_CLIENT_FAILED */ 0, "Could not add client");
 	    return -1;
 	}
 	return 0;
     }
 
-    qerror_report(QERR_INVALID_PARAMETER, "protocol");
+    qerror_report(/* QERR_INVALID_PARAMETER */ 30, "Invalid parameter 'name=%s'", "protocol");
     return -1;
 }
 
@@ -975,25 +975,25 @@  static int client_migrate_info(Monitor *mon, const QDict *qdict,
 
     if (strcmp(protocol, "spice") == 0) {
         if (!using_spice) {
-            qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
+            qerror_report(/* QERR_DEVICE_NOT_ACTIVE */ 20, "Device 'device=%s' has not been activated", "spice");
             return -1;
         }
 
         if (port == -1 && tls_port == -1) {
-            qerror_report(QERR_MISSING_PARAMETER, "port/tls-port");
+            qerror_report(/* QERR_MISSING_PARAMETER */ 42, "Parameter 'name=%s' is missing", "port/tls-port");
             return -1;
         }
 
         ret = qemu_spice_migrate_info(hostname, port, tls_port, subject,
                                       cb, opaque);
         if (ret != 0) {
-            qerror_report(QERR_UNDEFINED_ERROR);
+            qerror_report(/* QERR_UNDEFINED_ERROR */ 66, "An undefined error has occurred");
             return -1;
         }
         return 0;
     }
 
-    qerror_report(QERR_INVALID_PARAMETER, "protocol");
+    qerror_report(/* QERR_INVALID_PARAMETER */ 30, "Invalid parameter 'name=%s'", "protocol");
     return -1;
 }
 
@@ -3859,7 +3859,7 @@  static void handler_audit(Monitor *mon, const mon_cmd_t *cmd, int ret)
          *
          * Action: Report an internal error to the client if in QMP.
          */
-        qerror_report(QERR_UNDEFINED_ERROR);
+        qerror_report(/* QERR_UNDEFINED_ERROR */ 66, "An undefined error has occurred");
     }
 }
 
@@ -4162,7 +4162,7 @@  static int check_client_args_type(const QDict *client_args,
                 continue;
             }
             /* client arg doesn't exist */
-            qerror_report(QERR_INVALID_PARAMETER, client_arg_name);
+            qerror_report(/* QERR_INVALID_PARAMETER */ 30, "Invalid parameter 'name=%s'", client_arg_name);
             return -1;
         }
 
@@ -4175,8 +4175,7 @@  static int check_client_args_type(const QDict *client_args,
         case 'B':
         case 's':
             if (qobject_type(client_arg) != QTYPE_QSTRING) {
-                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
-                              "string");
+                qerror_report(/* QERR_INVALID_PARAMETER_TYPE */ 32, "Invalid parameter type for 'name=%s', expected: expected=%s", client_arg_name, "string");
                 return -1;
             }
         break;
@@ -4185,24 +4184,21 @@  static int check_client_args_type(const QDict *client_args,
         case 'M':
         case 'o':
             if (qobject_type(client_arg) != QTYPE_QINT) {
-                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
-                              "int");
+                qerror_report(/* QERR_INVALID_PARAMETER_TYPE */ 32, "Invalid parameter type for 'name=%s', expected: expected=%s", client_arg_name, "int");
                 return -1; 
             }
             break;
         case 'T':
             if (qobject_type(client_arg) != QTYPE_QINT &&
                 qobject_type(client_arg) != QTYPE_QFLOAT) {
-                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
-                              "number");
+                qerror_report(/* QERR_INVALID_PARAMETER_TYPE */ 32, "Invalid parameter type for 'name=%s', expected: expected=%s", client_arg_name, "number");
                return -1; 
             }
             break;
         case 'b':
         case '-':
             if (qobject_type(client_arg) != QTYPE_QBOOL) {
-                qerror_report(QERR_INVALID_PARAMETER_TYPE, client_arg_name,
-                              "bool");
+                qerror_report(/* QERR_INVALID_PARAMETER_TYPE */ 32, "Invalid parameter type for 'name=%s', expected: expected=%s", client_arg_name, "bool");
                return -1; 
             }
             break;
@@ -4246,7 +4242,7 @@  static int check_mandatory_args(const QDict *cmd_args,
         } else if (qstring_get_str(type)[0] != '-' &&
                    qstring_get_str(type)[1] != '?' &&
                    !qdict_haskey(client_args, cmd_arg_name)) {
-            qerror_report(QERR_MISSING_PARAMETER, cmd_arg_name);
+            qerror_report(/* QERR_MISSING_PARAMETER */ 42, "Parameter 'name=%s' is missing", cmd_arg_name);
             return -1;
         }
     }
@@ -4344,7 +4340,7 @@  static QDict *qmp_check_input_obj(QObject *input_obj)
     QDict *input_dict;
 
     if (qobject_type(input_obj) != QTYPE_QDICT) {
-        qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "object");
+        qerror_report(/* QERR_QMP_BAD_INPUT_OBJECT */ 55, "Expected 'expected=%s' in QMP input", "object");
         return NULL;
     }
 
@@ -4356,27 +4352,25 @@  static QDict *qmp_check_input_obj(QObject *input_obj)
 
         if (!strcmp(arg_name, "execute")) {
             if (qobject_type(arg_obj) != QTYPE_QSTRING) {
-                qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
-                              "string");
+                qerror_report(/* QERR_QMP_BAD_INPUT_OBJECT_MEMBER */ 56, "QMP input object member 'member=%s' expects 'expected=%s'", "execute", "string");
                 return NULL;
             }
             has_exec_key = 1;
         } else if (!strcmp(arg_name, "arguments")) {
             if (qobject_type(arg_obj) != QTYPE_QDICT) {
-                qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments",
-                              "object");
+                qerror_report(/* QERR_QMP_BAD_INPUT_OBJECT_MEMBER */ 56, "QMP input object member 'member=%s' expects 'expected=%s'", "arguments", "object");
                 return NULL;
             }
         } else if (!strcmp(arg_name, "id")) {
             /* FIXME: check duplicated IDs for async commands */
         } else {
-            qerror_report(QERR_QMP_EXTRA_INPUT_OBJECT_MEMBER, arg_name);
+            qerror_report(/* QERR_QMP_EXTRA_INPUT_OBJECT_MEMBER */ 57, "QMP input object member 'member=%s' is unexpected", arg_name);
             return NULL;
         }
     }
 
     if (!has_exec_key) {
-        qerror_report(QERR_QMP_BAD_INPUT_OBJECT, "execute");
+        qerror_report(/* QERR_QMP_BAD_INPUT_OBJECT */ 55, "Expected 'expected=%s' in QMP input", "execute");
         return NULL;
     }
 
@@ -4409,7 +4403,7 @@  static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
     obj = json_parser_parse(tokens, NULL);
     if (!obj) {
         // FIXME: should be triggered in json_parser_parse()
-        qerror_report(QERR_JSON_PARSING);
+        qerror_report(/* QERR_JSON_PARSING */ 37, "Invalid JSON syntax");
         goto err_out;
     }
 
@@ -4425,13 +4419,13 @@  static void handle_qmp_command(JSONMessageParser *parser, QList *tokens)
     cmd_name = qdict_get_str(input, "execute");
     trace_handle_qmp_command(mon, cmd_name);
     if (invalid_qmp_mode(mon, cmd_name)) {
-        qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
+        qerror_report(/* QERR_COMMAND_NOT_FOUND */ 9, "The command name=%s has not been found", cmd_name);
         goto err_out;
     }
 
     cmd = qmp_find_cmd(cmd_name);
     if (!cmd) {
-        qerror_report(QERR_COMMAND_NOT_FOUND, cmd_name);
+        qerror_report(/* QERR_COMMAND_NOT_FOUND */ 9, "The command name=%s has not been found", cmd_name);
         goto err_out;
     }
 
@@ -4693,8 +4687,7 @@  int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
     }
 
     if (monitor_ctrl_mode(mon)) {
-        qerror_report(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs),
-                      bdrv_get_encrypted_filename(bs));
+        qerror_report(/* QERR_DEVICE_ENCRYPTED */ 10, "Device 'device=%s' is encrypted (filename=filename=%s)", bdrv_get_device_name(bs), bdrv_get_encrypted_filename(bs));
         return -1;
     }
 
diff --git a/qemu-option.c b/qemu-option.c
index bb3886c..a351ed9 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -690,7 +690,7 @@  int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
         if (i == 0) {
             /* empty list -> allow any */;
         } else {
-            qerror_report(QERR_INVALID_PARAMETER, name);
+            qerror_report(/* QERR_INVALID_PARAMETER */ 30, "Invalid parameter 'name=%s'", name);
             return -1;
         }
     }
diff --git a/qerror.c b/qerror.c
index 267545e..6d61426 100644
--- a/qerror.c
+++ b/qerror.c
@@ -124,82 +124,23 @@  QDict *build_error_dict(int err_class, const char *msg)
     return err_dict;
 }
 
-static QDict *error_object_from_fmt(const char *fmt, va_list *va)
-{
-    QObject *obj;
-    QDict *ret;
-
-    obj = qobject_from_jsonv(fmt, va);
-    if (!obj) {
-        fprintf(stderr, "invalid json in error dict '%s'\n", fmt);
-        return NULL;
-    }
-    if (qobject_type(obj) != QTYPE_QDICT) {
-        fprintf(stderr, "error is not a dict '%s'\n", fmt);
-        goto out_free;
-    }
-
-    ret = qobject_to_qdict(obj);
-    obj = qdict_get(ret, "class");
-    if (!obj) {
-        fprintf(stderr, "missing 'class' key in '%s'\n", fmt);
-        goto out_free;
-    }
-    if (qobject_type(obj) != QTYPE_QSTRING) {
-        fprintf(stderr, "'class' key value should be a string in '%s'\n", fmt);
-        goto out_free;
-    }
-
-    obj = qdict_get(ret, "data");
-    if (!obj) {
-        fprintf(stderr, "missing 'data' key in '%s'\n", fmt);
-        goto out_free;
-    }
-    if (qobject_type(obj) != QTYPE_QDICT) {
-        fprintf(stderr, "'data' key value should be a dict in '%s'\n", fmt);
-        goto out_free;
-    }
-
-    return ret;
-
-out_free:
-    qobject_decref(obj);
-    return NULL;
-}
-
-static QDict *build_error_no_arg(const char *fmt)
-{
-    return qobject_to_qdict(qobject_from_jsonv(fmt, NULL));
-}
-
 /**
  * qerror_from_info(): Create a new QError from error information
  *
  * Return strong reference.
  */
-static QError *qerror_from_info(const char *fmt, va_list *va)
+static QError *qerror_from_info(int err_class, const char *fmt, va_list *va)
 {
     QError *qerr;
+    char msg[2048];
 
     qerr = qerror_new();
     loc_save(&qerr->loc);
 
-    qerr->error = error_object_from_fmt(fmt, va);
-    if (!qerr->error) {
-        goto bad_err;
-    }
-
-    qerr->err_msg = qerror_format(fmt, qerr->error);
-    if (!qerr->err_msg) {
-        QDECREF(qerr->error);
-        goto bad_err;
-    }
-
-    return qerr;
+    vsnprintf(msg, sizeof(msg), fmt, *va);
+    qerr->err_msg = g_strdup(msg);
+    qerr->error = build_error_dict(err_class, qerr->err_msg);
 
-bad_err:
-    qerr->error = build_error_no_arg(QERR_UNDEFINED_ERROR);
-    qerr->err_msg = qerror_format(QERR_UNDEFINED_ERROR, qerr->error);
     return qerr;
 }
 
@@ -322,13 +263,13 @@  static void qerror_print(QError *qerror)
     QDECREF(qstring);
 }
 
-void qerror_report(const char *fmt, ...)
+void qerror_report(int err_class, const char *fmt, ...)
 {
     va_list va;
     QError *qerror;
 
     va_start(va, fmt);
-    qerror = qerror_from_info(fmt, &va);
+    qerror = qerror_from_info(err_class, fmt, &va);
     va_end(va);
 
     if (monitor_cur_is_qmp()) {
diff --git a/qerror.h b/qerror.h
index c4f6053..32e9a22 100644
--- a/qerror.h
+++ b/qerror.h
@@ -32,7 +32,7 @@  typedef struct QError {
 } QError;
 
 QString *qerror_human(const QError *qerror);
-void qerror_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2);
+void qerror_report(int err_class, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
 void qerror_report_err(Error *err);
 void assert_no_error(Error *err);
 char *qerror_format(const char *fmt, QDict *error);