diff --git a/src/station.c b/src/station.c
index 2473de2a..733b4196 100644
--- a/src/station.c
+++ b/src/station.c
@@ -147,15 +147,49 @@ struct roam_bss {
 	uint8_t addr[6];
 	uint16_t rank;
 	int32_t signal_strength;
+	bool reassoc: 1;
 };
 
-static struct roam_bss *roam_bss_from_scan_bss(const struct scan_bss *bss)
+static bool station_can_fast_transition(struct handshake_state *hs,
+					const struct scan_bss *bss)
+{
+	uint16_t mdid;
+
+	if (!hs->mde)
+		return false;
+
+	if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
+						&mdid, NULL, NULL) < 0)
+		return false;
+
+	if (!(bss->mde_present && l_get_le16(bss->mde) == mdid))
+		return false;
+
+	if (hs->supplicant_ie != NULL) {
+		struct ie_rsn_info rsn_info;
+
+		if (!IE_AKM_IS_FT(hs->akm_suite))
+			return false;
+
+		if (scan_bss_get_rsn_info(bss, &rsn_info) < 0)
+			return false;
+
+		if (!IE_AKM_IS_FT(rsn_info.akm_suites))
+			return false;
+	}
+
+	return true;
+}
+
+static struct roam_bss *roam_bss_from_scan_bss(struct handshake_state *hs,
+						const struct scan_bss *bss)
 {
 	struct roam_bss *rbss = l_new(struct roam_bss, 1);
 
 	memcpy(rbss->addr, bss->addr, 6);
 	rbss->rank = bss->rank;
 	rbss->signal_strength = bss->signal_strength;
+	rbss->reassoc = !station_can_fast_transition(hs, bss);
 
 	return rbss;
 }
@@ -1942,37 +1976,6 @@ static void station_early_neighbor_report_cb(struct netdev *netdev, int err,
 				&station->roam_freqs);
 }
 
-static bool station_can_fast_transition(struct handshake_state *hs,
-					struct scan_bss *bss)
-{
-	uint16_t mdid;
-
-	if (!hs->mde)
-		return false;
-
-	if (ie_parse_mobility_domain_from_data(hs->mde, hs->mde[1] + 2,
-						&mdid, NULL, NULL) < 0)
-		return false;
-
-	if (!(bss->mde_present && l_get_le16(bss->mde) == mdid))
-		return false;
-
-	if (hs->supplicant_ie != NULL) {
-		struct ie_rsn_info rsn_info;
-
-		if (!IE_AKM_IS_FT(hs->akm_suite))
-			return false;
-
-		if (scan_bss_get_rsn_info(bss, &rsn_info) < 0)
-			return false;
-
-		if (!IE_AKM_IS_FT(rsn_info.akm_suites))
-			return false;
-	}
-
-	return true;
-}
-
 static void station_disconnect_on_error_cb(struct netdev *netdev, bool success,
 					void *user_data)
 {
@@ -2169,10 +2172,14 @@ static int station_transition_reassociate(struct station *station,
 	if (ret < 0)
 		return ret;
 
+	l_debug("");
+
 	station->connected_bss = bss;
 	station->preparing_roam = false;
 	station_enter_state(station, STATION_STATE_ROAMING);
 
+	station_debug_event(station, "reassoc-roam");
+
 	return 0;
 }
 
@@ -2259,27 +2266,51 @@ static void station_preauthenticate_cb(struct netdev *netdev,
 	}
 }
 
-static void station_transition_start(struct station *station);
+static void station_transition_start(struct station *station, bool no_ft);
 
 static bool station_ft_work_ready(struct wiphy_radio_work_item *item)
 {
 	struct station *station = l_container_of(item, struct station, ft_work);
-	struct roam_bss *rbss = l_queue_pop_head(station->roam_bss_list);
-	struct scan_bss *bss = network_bss_find_by_addr(
-					station->connected_network, rbss->addr);
+	L_AUTO_FREE_VAR(struct roam_bss *, rbss) = l_queue_pop_head(
+							station->roam_bss_list);
+	struct scan_bss *bss;
 	int ret;
 
-	l_free(rbss);
+	/* Already failed FT, then failed reassociation, disregard this BSS */
+	if (rbss->reassoc) {
+		l_free(l_steal_ptr(rbss));
+
+		rbss = l_queue_pop_head(station->roam_bss_list);
+		if (!rbss)
+			goto assoc_failed;
+	}
 
 	/* Very unlikely, but the BSS could have gone away */
+	bss = network_bss_find_by_addr(station->connected_network, rbss->addr);
 	if (!bss)
 		goto try_next;
 
 	ret = ft_associate(netdev_get_ifindex(station->netdev), bss->addr);
-	if (ret == -ENOENT) {
+	if (ret > 0) {
+		if (ret != MMPDU_STATUS_CODE_INVALID_PMKID) {
+			station_debug_event(station, "ft-roam-failed");
+			goto try_next;
+		}
+
+		rbss->reassoc = true;
+
+		l_queue_push_head(station->roam_bss_list, rbss);
+
+		station_debug_event(station, "ft-fallback-to-reassoc");
+
+		/* FT failed, attempt reassociation as a last resort */
+		station_transition_start(station, true);
+		l_steal_ptr(rbss);
+		return true;
+	} else if (ret == -ENOENT) {
 		station_debug_event(station, "ft-roam-failed");
 try_next:
-		station_transition_start(station);
+		station_transition_start(station, false);
 		return true;
 	} else if (ret < 0)
 		goto assoc_failed;
@@ -2288,6 +2319,8 @@ try_next:
 	station->preparing_roam = false;
 	station_enter_state(station, STATION_STATE_FT_ROAMING);
 
+	station_debug_event(station, "ft-roam");
+
 	return true;
 
 assoc_failed:
@@ -2349,7 +2382,8 @@ done:
 }
 
 static bool station_try_next_transition(struct station *station,
-					struct scan_bss *bss)
+					struct scan_bss *bss,
+					bool no_ft)
 {
 	struct handshake_state *hs = netdev_get_handshake(station->netdev);
 	struct network *connected = station->connected_network;
@@ -2364,7 +2398,7 @@ static bool station_try_next_transition(struct station *station,
 	station->ap_directed_roaming = false;
 
 	/* Can we use Fast Transition? */
-	if (station_can_fast_transition(hs, bss))
+	if (station_can_fast_transition(hs, bss) && !no_ft)
 		return station_fast_transition(station, bss);
 
 	/* Non-FT transition */
@@ -2412,7 +2446,7 @@ static bool station_try_next_transition(struct station *station,
 	return true;
 }
 
-static void station_transition_start(struct station *station)
+static void station_transition_start(struct station *station, bool no_ft)
 {
 	struct roam_bss *rbss;
 	bool roaming = false;
@@ -2425,7 +2459,7 @@ static void station_transition_start(struct station *station)
 		struct scan_bss *bss = network_bss_find_by_addr(
 					station->connected_network, rbss->addr);
 
-		roaming = station_try_next_transition(station, bss);
+		roaming = station_try_next_transition(station, bss, no_ft);
 		if (roaming)
 			break;
 
@@ -2581,7 +2615,7 @@ static bool station_roam_scan_notify(int err, struct l_queue *bss_list,
 		 */
 		station_update_roam_bss(station, bss);
 
-		rbss = roam_bss_from_scan_bss(bss);
+		rbss = roam_bss_from_scan_bss(hs, bss);
 
 		l_queue_insert(station->roam_bss_list, rbss,
 				roam_bss_rank_compare, NULL);
@@ -2600,7 +2634,7 @@ next:
 		goto fail;
 	}
 
-	station_transition_start(station);
+	station_transition_start(station, false);
 
 	return true;
 
@@ -4584,6 +4618,7 @@ static bool station_force_roam_scan_notify(int err, struct l_queue *bss_list,
 {
 	struct station_roam_data *data = user_data;
 	struct station *station = data->station;
+	struct handshake_state *hs = netdev_get_handshake(station->netdev);
 	struct scan_bss *target;
 	struct l_dbus_message *reply;
 
@@ -4603,11 +4638,11 @@ static bool station_force_roam_scan_notify(int err, struct l_queue *bss_list,
 	/* The various roam routines expect this to be set from scanning */
 	station->preparing_roam = true;
 	l_queue_push_tail(station->roam_bss_list,
-				roam_bss_from_scan_bss(target));
+				roam_bss_from_scan_bss(hs, target));
 
 	station_update_roam_bss(station, target);
 
-	station_transition_start(station);
+	station_transition_start(station, false);
 
 	reply = l_dbus_message_new_method_return(data->pending);
 
