diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index f6b8b7e78..ad83acc30 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -17,6 +17,7 @@
misc/animationUtils.js
misc/config.js
misc/dateUtils.js
+ misc/dbusErrors.js
misc/dbusUtils.js
misc/dependencies.js
misc/errorUtils.js
diff --git a/js/misc/dbusErrors.js b/js/misc/dbusErrors.js
new file mode 100644
index 000000000..5e4d62e2c
--- /dev/null
+++ b/js/misc/dbusErrors.js
@@ -0,0 +1,29 @@
+/* eslint-disable no-unused-vars */
+import GLib from 'gi://GLib';
+import Gio from 'gi://Gio';
+
+function decamelcase(str, sep) {
+ return str.replace(/(.)([A-Z])/g, `$1${sep}$2`);
+}
+
+function registerErrorDomain(domain, errorNames, prefix = 'org.gnome.Shell') {
+ const domainName =
+ `shell-${decamelcase(domain, '-').toLowerCase()}-error`;
+ const quark = GLib.quark_from_string(domainName);
+
+ for (const [code, name] of errorNames.entries()) {
+ Gio.dbus_error_register_error(quark,
+ code, `${prefix}.${domain}.Error.${name}`);
+ }
+ return quark;
+}
+
+function createErrorEnum(errorNames) {
+ const obj = {};
+
+ for (const [code, name] of errorNames.entries()) {
+ const propName = decamelcase(name, '_').toUpperCase();
+ obj[propName] = code;
+ }
+ return obj;
+}