diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 3f43dcdc88..ed85860da5 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -435,7 +435,7 @@ struct MainWindow : Window
 	virtual void OnInvalidateData(int data)
 	{
 		/* Forward the message to the appropiate toolbar (ingame or scenario editor) */
-		InvalidateWindowData(WC_MAIN_TOOLBAR, 0, data);
+		InvalidateWindowData(WC_MAIN_TOOLBAR, 0, data, true);
 	}
 
 	static Hotkey<MainWindow> global_hotkeys[];
diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp
index 9e770cb41c..c86f6c6a36 100644
--- a/src/misc_gui.cpp
+++ b/src/misc_gui.cpp
@@ -199,6 +199,7 @@ public:
 		if (c != NULL) {
 			Money old_money = c->money;
 			c->money = INT64_MAX;
+			assert(_current_company == _local_company);
 			CommandCost costclear = DoCommand(tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR);
 			c->money = old_money;
 			if (costclear.Succeeded()) {
diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp
index 99512515fe..3359f796fd 100644
--- a/src/newgrf_debug_gui.cpp
+++ b/src/newgrf_debug_gui.cpp
@@ -518,7 +518,9 @@ void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
 	WindowNumber wno = GetInspectWindowNumber(feature, index);
 	DeleteWindowById(WC_NEWGRF_INSPECT, wno);
 
-	/* Reinitialise the land information window to remove the "debug" sprite if needed. */
+	/* Reinitialise the land information window to remove the "debug" sprite if needed.
+	 * Note: Since we might be called from a command here, it is important to not execute
+	 * the invalidation immediatelly. The landinfo window tests commands itself. */
 	InvalidateWindowData(WC_LAND_INFO, 0, 1);
 }
 
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 754ae91986..e8beb46a61 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -264,7 +264,7 @@ void Train::ConsistChanged(bool same_length)
 	if (this->IsFrontEngine()) {
 		this->UpdateAcceleration();
 		SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
-		InvalidateWindowData(WC_VEHICLE_REFIT, this->index);
+		InvalidateWindowData(WC_VEHICLE_REFIT, this->index); // Important, do not invalidate immediatelly. The refit window tests commands.
 	}
 }
 
@@ -1089,7 +1089,7 @@ static void NormaliseTrainHead(Train *head)
 	if (!head->IsFrontEngine()) return;
 
 	/* Update the refit button and window */
-	InvalidateWindowData(WC_VEHICLE_REFIT, head->index);
+	InvalidateWindowData(WC_VEHICLE_REFIT, head->index); // Important, do not invalidate immediatelly. The refit window tests commands.
 	SetWindowWidgetDirty(WC_VEHICLE_VIEW, head->index, VVW_WIDGET_REFIT_VEH);
 
 	/* If we don't have a unit number yet, set one. */
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index e3ffbbc91e..f1dd8a7cde 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -2270,7 +2270,7 @@ void Vehicle::RemoveFromShared()
 	} else if (were_first) {
 		/* If we were the first one, update to the new first one.
 		 * Note: FirstShared() is already the new first */
-		InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.Pack(), this->FirstShared()->index | (1U << 31));
+		InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.Pack(), this->FirstShared()->index | (1U << 31), true);
 	}
 
 	this->next_shared     = NULL;
diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp
index 96580dac9f..61ef82ef53 100644
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -585,6 +585,7 @@ struct RefitWindow : public Window {
 	 */
 	StringID GetCapacityString(RefitOption *option) const
 	{
+		assert(_current_company == _local_company);
 		Vehicle *v = Vehicle::Get(this->window_number);
 		CommandCost cost = DoCommand(v->tile, this->selected_vehicle, option->cargo | option->subtype << 8 |
 				this->num_vehicles << 16, DC_QUERY_COST, GetCmdRefitVeh(v->type));
@@ -1119,7 +1120,7 @@ static inline void ChangeVehicleWindow(WindowClass window_class, VehicleID from_
 			_thd.window_number = to_index;
 		}
 
-		/* Notify the window */
+		/* Notify the window immediatelly, without scheduling. */
 		w->InvalidateData();
 	}
 }
diff --git a/src/window.cpp b/src/window.cpp
index 2c6f1f1e16..ac4c76b3ba 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -2420,6 +2420,7 @@ void UpdateWindows()
 
 			if (!(w->flags4 & WF_WHITE_BORDER_MASK)) w->SetDirty();
 		}
+		w->ProcessScheduledInvalidations();
 	}
 
 	DrawDirtyBlocks();
@@ -2476,29 +2477,47 @@ void SetWindowClassesDirty(WindowClass cls)
 
 /**
  * Mark window data of the window of a given class and specific window number as invalid (in need of re-computing)
+ * Note that by default the invalidation is not executed immediatelly but is scheduled till the next redraw.
+ * The asynchronous execution is important to prevent GUI code being executed from command scope.
  * @param cls Window class
  * @param number Window number within the class
  * @param data The data to invalidate with
+ * @param immediatelly If true then do not schedule the event, but execute immediatelly.
  */
-void InvalidateWindowData(WindowClass cls, WindowNumber number, int data)
+void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool immediatelly)
 {
 	Window *w;
 	FOR_ALL_WINDOWS_FROM_BACK(w) {
-		if (w->window_class == cls && w->window_number == number) w->InvalidateData(data);
+		if (w->window_class == cls && w->window_number == number) {
+			if (immediatelly) {
+				w->InvalidateData(data);
+			} else {
+				w->ScheduleInvalidateData(data);
+			}
+		}
 	}
 }
 
 /**
  * Mark window data of all windows of a given class as invalid (in need of re-computing)
+ * Note that by default the invalidation is not executed immediatelly but is scheduled till the next redraw.
+ * The asynchronous execution is important to prevent GUI code being executed from command scope.
  * @param cls Window class
  * @param data The data to invalidate with
+ * @param immediatelly If true then do not schedule the event, but execute immediatelly.
  */
-void InvalidateWindowClassesData(WindowClass cls, int data)
+void InvalidateWindowClassesData(WindowClass cls, int data, bool immediatelly)
 {
 	Window *w;
 
 	FOR_ALL_WINDOWS_FROM_BACK(w) {
-		if (w->window_class == cls) w->InvalidateData(data);
+		if (w->window_class == cls) {
+			if (immediatelly) {
+				w->InvalidateData(data);
+			} else {
+				w->ScheduleInvalidateData(data);
+			}
+		}
 	}
 }
 
diff --git a/src/window_func.h b/src/window_func.h
index 3d51644f6d..933d198773 100644
--- a/src/window_func.h
+++ b/src/window_func.h
@@ -34,8 +34,8 @@ void ResetWindowSystem();
 void SetupColoursAndInitialWindow();
 void InputLoop();
 
-void InvalidateWindowData(WindowClass cls, WindowNumber number, int data = 0);
-void InvalidateWindowClassesData(WindowClass cls, int data = 0);
+void InvalidateWindowData(WindowClass cls, WindowNumber number, int data = 0, bool immediatelly = false);
+void InvalidateWindowClassesData(WindowClass cls, int data = 0, bool immediatelly = false);
 
 void DeleteNonVitalWindows();
 void DeleteAllNonVitalWindows();
diff --git a/src/window_gui.h b/src/window_gui.h
index 724d77880d..3254ee8c4c 100644
--- a/src/window_gui.h
+++ b/src/window_gui.h
@@ -17,6 +17,7 @@
 #include "company_type.h"
 #include "tile_type.h"
 #include "widget_type.h"
+#include "core/smallvec_type.hpp"
 
 /** State of handling an event. */
 enum EventState {
@@ -221,6 +222,8 @@ protected:
 	void InitializePositionSize(int x, int y, int min_width, int min_height);
 	void FindWindowPlacementAndResize(int def_width, int def_height);
 
+	SmallVector<int, 4> scheduled_invalidation_data;  ///< Data of scheduled OnInvalidateData() calls.
+
 public:
 	Window();
 
@@ -438,6 +441,28 @@ public:
 		this->OnInvalidateData(data);
 	}
 
+	/**
+	 * Schedule a invalidation call for next redraw.
+	 * Important for asynchronous invalidation from commands.
+	 * @param data The data to invalidate with
+	 */
+	void ScheduleInvalidateData(int data = 0)
+	{
+		this->SetDirty();
+		*this->scheduled_invalidation_data.Append() = data;
+	}
+
+	/**
+	 * Process all scheduled invalidations.
+	 */
+	void ProcessScheduledInvalidations()
+	{
+		for (int *data = this->scheduled_invalidation_data.Begin(); this->window_class != WC_INVALID && data != this->scheduled_invalidation_data.End(); data++) {
+			this->OnInvalidateData(*data);
+		}
+		this->scheduled_invalidation_data.Clear();
+	}
+
 	/*** Event handling ***/
 
 	/**