diff --git a/packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx b/packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx
index 8844739a4900f2cb53dd64c854988eac5ab53209..d80da0f072d61eb61bf1a3ee8a9dd3aefb3d9b7b 100644
--- a/packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx
+++ b/packages/desktop-client/src/components/modals/CreateEncryptionKeyModal.tsx
@@ -43,7 +43,7 @@ export function CreateEncryptionKeyModal({
 
   const isRecreating = options.recreate;
 
-  async function onCreateKey() {
+  async function onCreateKey(close: () => void) {
     if (password !== '' && !loading) {
       setLoading(true);
       setError(null);
@@ -60,6 +60,7 @@ export function CreateEncryptionKeyModal({
       dispatch(sync());
 
       setLoading(false);
+      close();
     }
   }
 
@@ -151,8 +152,7 @@ export function CreateEncryptionKeyModal({
           <Form
             onSubmit={e => {
               e.preventDefault();
-              onCreateKey();
-              close();
+              onCreateKey(close);
             }}
           >
             <View style={{ alignItems: 'center' }}>
diff --git a/packages/desktop-client/src/components/modals/EditRule.jsx b/packages/desktop-client/src/components/modals/EditRule.jsx
index 2256bc2877563674cca9dab9343c7078ab1b532a..ad092f26da599a997f50bc30f16544df5b551120 100644
--- a/packages/desktop-client/src/components/modals/EditRule.jsx
+++ b/packages/desktop-client/src/components/modals/EditRule.jsx
@@ -861,7 +861,7 @@ export function EditRule({ defaultRule, onSave: originalOnSave }) {
     });
   }
 
-  async function onSave() {
+  async function onSave(close) {
     const rule = {
       ...defaultRule,
       stage,
@@ -879,7 +879,16 @@ export function EditRule({ defaultRule, onSave: originalOnSave }) {
       }
 
       if (error.actionErrors) {
-        setActionSplits(applyErrors(actionSplits, error.actionErrors));
+        let usedErrorIdx = 0;
+        setActionSplits(
+          actionSplits.map(item => ({
+            ...item,
+            actions: item.actions.map(action => ({
+              ...action,
+              error: error.actionErrors[usedErrorIdx++] ?? null,
+            })),
+          })),
+        );
       }
     } else {
       // If adding a rule, we got back an id
@@ -888,6 +897,7 @@ export function EditRule({ defaultRule, onSave: originalOnSave }) {
       }
 
       originalOnSave?.(rule);
+      close();
     }
   }
 
@@ -1145,13 +1155,7 @@ export function EditRule({ defaultRule, onSave: originalOnSave }) {
                   style={{ marginTop: 20 }}
                 >
                   <Button onClick={close}>Cancel</Button>
-                  <Button
-                    variant="primary"
-                    onPress={() => {
-                      onSave();
-                      close();
-                    }}
-                  >
+                  <Button variant="primary" onPress={() => onSave(close)}>
                     Save
                   </Button>
                 </Stack>
diff --git a/packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx b/packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx
index c48a6e175fe92452f98137c81fdb087ae8ef49be..cd783296bb2a2519a2f354801dd869b101393448 100644
--- a/packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx
+++ b/packages/desktop-client/src/components/modals/FixEncryptionKeyModal.tsx
@@ -37,7 +37,7 @@ export function FixEncryptionKeyModal({
   const [showPassword, setShowPassword] = useState(false);
   const { isNarrowWidth } = useResponsive();
 
-  async function onUpdateKey() {
+  async function onUpdateKey(close: () => void) {
     if (password !== '' && !loading) {
       setLoading(true);
       setError(null);
@@ -53,6 +53,7 @@ export function FixEncryptionKeyModal({
       }
 
       onSuccess?.();
+      close();
     }
   }
 
@@ -104,8 +105,7 @@ export function FixEncryptionKeyModal({
           <Form
             onSubmit={e => {
               e.preventDefault();
-              onUpdateKey();
-              close();
+              onUpdateKey(close);
             }}
           >
             <View
diff --git a/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx b/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx
index 3ba1ea3d0f9753f8eb359234b30bcbf71ea273f3..fc91a66a1a9627145043d75d5f71bf115fa1973d 100644
--- a/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx
+++ b/packages/desktop-client/src/components/modals/GoCardlessInitialise.tsx
@@ -29,7 +29,7 @@ export const GoCardlessInitialise = ({
   const [isValid, setIsValid] = useState(true);
   const [isLoading, setIsLoading] = useState(false);
 
-  const onSubmit = async () => {
+  const onSubmit = async (close: () => void) => {
     if (!secretId || !secretKey) {
       setIsValid(false);
       return;
@@ -50,6 +50,7 @@ export const GoCardlessInitialise = ({
 
     onSuccess();
     setIsLoading(false);
+    close();
   };
 
   return (
@@ -113,8 +114,7 @@ export const GoCardlessInitialise = ({
               variant="primary"
               isLoading={isLoading}
               onPress={() => {
-                onSubmit();
-                close();
+                onSubmit(close);
               }}
             >
               Save and continue
diff --git a/packages/desktop-client/src/components/modals/ImportTransactions.jsx b/packages/desktop-client/src/components/modals/ImportTransactions.jsx
index 56242cd4f56472818a72790a4af01145d819b35e..8fea03dbf0c4ae072f91d2750005d7cff24e8034 100644
--- a/packages/desktop-client/src/components/modals/ImportTransactions.jsx
+++ b/packages/desktop-client/src/components/modals/ImportTransactions.jsx
@@ -1089,7 +1089,7 @@ export function ImportTransactions({ options }) {
     setTransactions(newTransactions);
   }
 
-  async function onImport() {
+  async function onImport(close) {
     setLoadingState('importing');
 
     const finalTransactions = [];
@@ -1206,6 +1206,7 @@ export function ImportTransactions({ options }) {
     if (onImported) {
       onImported(didChange);
     }
+    close();
   }
 
   const runImportPreviewCallback = useCallback(async () => {
@@ -1682,8 +1683,7 @@ export function ImportTransactions({ options }) {
                 }
                 isLoading={loadingState === 'importing'}
                 onPress={() => {
-                  onImport();
-                  close();
+                  onImport(close);
                 }}
               >
                 Import{' '}
diff --git a/packages/desktop-client/src/components/modals/SimpleFinInitialise.tsx b/packages/desktop-client/src/components/modals/SimpleFinInitialise.tsx
index 2e5c356e237491cd1064e92ff2085c6a08fe8180..21613af5c1f690e6751bd06c5c8ee75e52a7cc3c 100644
--- a/packages/desktop-client/src/components/modals/SimpleFinInitialise.tsx
+++ b/packages/desktop-client/src/components/modals/SimpleFinInitialise.tsx
@@ -28,7 +28,7 @@ export const SimpleFinInitialise = ({
   const [isValid, setIsValid] = useState(true);
   const [isLoading, setIsLoading] = useState(false);
 
-  const onSubmit = async () => {
+  const onSubmit = async (close: () => void) => {
     if (!token) {
       setIsValid(false);
       return;
@@ -43,6 +43,7 @@ export const SimpleFinInitialise = ({
 
     onSuccess();
     setIsLoading(false);
+    close();
   };
 
   return (
@@ -89,8 +90,7 @@ export const SimpleFinInitialise = ({
               variant="primary"
               isLoading={isLoading}
               onPress={() => {
-                onSubmit();
-                close();
+                onSubmit(close);
               }}
             >
               Save and continue
diff --git a/packages/desktop-client/src/components/schedules/ScheduleDetails.jsx b/packages/desktop-client/src/components/schedules/ScheduleDetails.jsx
index 5c89c4fc27519d0c6f16501248b949cdfc1711c3..995a8aa7163fe44634e84f3bba341e57afe74a2f 100644
--- a/packages/desktop-client/src/components/schedules/ScheduleDetails.jsx
+++ b/packages/desktop-client/src/components/schedules/ScheduleDetails.jsx
@@ -353,7 +353,7 @@ export function ScheduleDetails({ id, transaction }) {
     transaction ? [transaction.id] : [],
   );
 
-  async function onSave() {
+  async function onSave(close) {
     dispatch({ type: 'form-error', error: null });
     if (state.fields.name) {
       const { data: sameName } = await runQuery(
@@ -396,11 +396,14 @@ export function ScheduleDetails({ id, transaction }) {
         error:
           'An error occurred while saving. Please visit https://actualbudget.org/contact/ for support.',
       });
-    } else {
-      if (adding) {
-        await onLinkTransactions([...selectedInst.items], res.data);
-      }
+      return;
     }
+
+    if (adding) {
+      await onLinkTransactions([...selectedInst.items], res.data);
+    }
+
+    close();
   }
 
   async function onEditRule(ruleId) {
@@ -788,8 +791,7 @@ export function ScheduleDetails({ id, transaction }) {
             <Button
               variant="primary"
               onPress={() => {
-                onSave();
-                close();
+                onSave(close);
               }}
             >
               {adding ? 'Add' : 'Save'}
diff --git a/packages/loot-core/src/server/accounts/rules.test.ts b/packages/loot-core/src/server/accounts/rules.test.ts
index 8368131e65783ee3365e2c669887d4865aff9b26..556230081aba952e8a286b0ab40f8e9b7b3a5222 100644
--- a/packages/loot-core/src/server/accounts/rules.test.ts
+++ b/packages/loot-core/src/server/accounts/rules.test.ts
@@ -12,6 +12,7 @@ import {
 const fieldTypes = new Map(
   Object.entries({
     id: 'id',
+    account: 'id',
     date: 'date',
     name: 'string',
     category: 'string',
@@ -322,6 +323,12 @@ describe('Action', () => {
       new Action(null, 'name', 'James', null, fieldTypes);
     }).toThrow(/invalid action operation/i);
   });
+
+  test('empty account values result in error', () => {
+    expect(() => {
+      new Action('set', 'account', '', null, fieldTypes);
+    }).toThrow(/Field cannot be empty/i);
+  });
 });
 
 describe('Rule', () => {
diff --git a/packages/loot-core/src/server/accounts/rules.ts b/packages/loot-core/src/server/accounts/rules.ts
index 4116cd01048a3fe2c3d5000c5b702672d1bd067e..a72c8b628cde71b0ae413d1e91ac868f8b3a4b3b 100644
--- a/packages/loot-core/src/server/accounts/rules.ts
+++ b/packages/loot-core/src/server/accounts/rules.ts
@@ -471,6 +471,10 @@ export class Action {
       this.type = 'id';
     }
 
+    if (field === 'account') {
+      assert(value, 'no-null', `Field cannot be empty: ${field}`);
+    }
+
     this.op = op;
     this.rawValue = value;
     this.value = value;
diff --git a/packages/loot-core/src/server/rules/app.ts b/packages/loot-core/src/server/rules/app.ts
index dd8bd11c68215eb5f96cf7ed9922f6d8e699caf5..01d37e1b764afd1e3b44b71c29f5aadea5581102 100644
--- a/packages/loot-core/src/server/rules/app.ts
+++ b/packages/loot-core/src/server/rules/app.ts
@@ -15,22 +15,22 @@ function validateRule(rule: Partial<RuleEntity>) {
   // Returns an array of errors, the array is the same link as the
   // passed-in `array`, or null if there are no errors
   function runValidation<T>(array: T[], validate: (item: T) => unknown) {
-    const result = array
-      .map(item => {
-        try {
-          validate(item);
-        } catch (e) {
-          if (e instanceof RuleError) {
-            console.warn('Invalid rule', e);
-            return e.type;
-          }
-          throw e;
+    const result = array.map(item => {
+      try {
+        validate(item);
+      } catch (e) {
+        if (e instanceof RuleError) {
+          console.warn('Invalid rule', e);
+          return e.type;
         }
-        return null;
-      })
-      .filter((res): res is string => typeof res === 'string');
+        throw e;
+      }
+      return null;
+    });
 
-    return result.length ? result : null;
+    return result.filter((res): res is string => typeof res === 'string').length
+      ? result
+      : null;
   }
 
   const conditionErrors = runValidation(
diff --git a/upcoming-release-notes/3149.md b/upcoming-release-notes/3149.md
new file mode 100644
index 0000000000000000000000000000000000000000..509736541329025c3e601717c8b26c21d6414481
--- /dev/null
+++ b/upcoming-release-notes/3149.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [MatissJanis]
+---
+
+Fix missing error handling in rules modal.