diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index b32db8618e..10a7b87c3d 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -149,6 +149,11 @@ DeviceState *qdev_new(const char *name)
     return DEVICE(object_new_dynamic(name, &error_abort));
 }
 
+DeviceState *qdev_new_dynamic(const char *name, Error **errp)
+{
+    return DEVICE(object_new_dynamic(name, errp));
+}
+
 DeviceState *qdev_try_new(const char *name)
 {
     ObjectClass *oc = module_object_class_by_name(name);
@@ -158,6 +163,15 @@ DeviceState *qdev_try_new(const char *name)
     return DEVICE(object_new_with_class(oc, &error_abort));
 }
 
+DeviceState *qdev_try_new_dynamic(const char *name, Error **errp)
+{
+    ObjectClass *oc = module_object_class_by_name(name);
+    if (!oc) {
+        return NULL;
+    }
+    return DEVICE(object_new_with_class(oc, errp));
+}
+
 static QTAILQ_HEAD(, DeviceListener) device_listeners
     = QTAILQ_HEAD_INITIALIZER(device_listeners);
 
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 5be9844412..68ebaec058 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -435,26 +435,80 @@ compat_props_add(GPtrArray *arr,
  * qdev_new: Create a device on the heap
  * @name: device type to create (we assert() that this type exists)
  *
+ * This method should be used where @name is statically specified
+ * from a const string at build time, where the caller does not expect
+ * failure to be possible.
+ *
  * This only allocates the memory and initializes the device state
  * structure, ready for the caller to set properties if they wish.
  * The device still needs to be realized.
  *
+ * If an instance of @name is not permitted to be instantiated, an
+ * assert will be raised. This can happen if @name is abstract.
+ *
  * Return: a derived DeviceState object with a reference count of 1.
  */
 DeviceState *qdev_new(const char *name);
 
+/**
+ * qdev_new_dynamic: Create a device on the heap
+ * @name: device type to create (we assert() that this type exists)
+ * @errp: pointer to be filled with error details on failure
+ *
+ * This method must be used where @name is dynamically chosen
+ * at runtime, which has the possibility of unexpected choices leading
+ * to failures.
+ *
+ * This only allocates the memory and initializes the device state
+ * structure, ready for the caller to set properties if they wish.
+ * The device still needs to be realized.
+ *
+ * If an instance of @name is not permitted to be instantiated, an
+ * error will be reported. This can happen if @name is abstract.
+ *
+ * Return: a derived DeviceState object with a reference count of 1.
+ */
+DeviceState *qdev_new_dynamic(const char *name, Error **errp);
+
 /**
  * qdev_try_new: Try to create a device on the heap
  * @name: device type to create
  *
+ * This method should be used where @name is statically specified
+ * from a const string at build time, where the caller does not expect
+ * failure to be possible.
+ *
  * This is like qdev_new(), except it returns %NULL when type @name
  * does not exist, rather than asserting.
  *
+ * If an instance of @name is not permitted to be instantiated, an
+ * assert will be raised. This can happen if @name is abstract.
+ *
  * Return: a derived DeviceState object with a reference count of 1 or
  * NULL if type @name does not exist.
  */
 DeviceState *qdev_try_new(const char *name);
 
+/**
+ * qdev_try_new_dynamic: Try to create a device on the heap
+ * @name: device type to create
+ * @errp: pointer to be filled with error details on failure
+ *
+ * This method must be used where @name is dynamically chosen
+ * at runtime, which has the possibility of unexpected choices leading
+ * to failures.
+ *
+ * This is like qdev_new_dynamic(), except it returns %NULL when type @name
+ * does not exist, rather than asserting.
+ *
+ * If an instance of @name is not permitted to be instantiated, an
+ * error will be reported. This can happen if @name is abstract.
+ *
+ * Return: a derived DeviceState object with a reference count of 1 or
+ * NULL if type @name does not exist.
+ */
+DeviceState *qdev_try_new_dynamic(const char *name, Error **errp);
+
 /**
  * qdev_is_realized() - check if device is realized
  * @dev: The device to check.
