diff --git a/system/stack/acl/btm_acl.cc b/system/stack/acl/btm_acl.cc
index 05130f4fab870df9c101df7e31b1eb7e1d29ec17..e8d71088124925faff1632c8e671a05704b647d3 100644
--- a/system/stack/acl/btm_acl.cc
+++ b/system/stack/acl/btm_acl.cc
@@ -2708,8 +2708,37 @@ void acl_disconnect_from_handle(uint16_t handle, tHCI_STATUS reason,
   acl_disconnect_after_role_switch(handle, reason, comment);
 }
 
+// BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E
+// 7.1.6 Disconnect command
+// Only a subset of reasons are valid and will be accepted
+// by the controller
+bool is_disconnect_reason_valid(const tHCI_REASON& reason) {
+  switch (reason) {
+    case HCI_ERR_AUTH_FAILURE:
+    case HCI_ERR_PEER_USER:
+    case HCI_ERR_REMOTE_LOW_RESOURCE:
+    case HCI_ERR_REMOTE_POWER_OFF:
+    case HCI_ERR_UNSUPPORTED_REM_FEATURE:
+    case HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED:
+    case HCI_ERR_UNACCEPT_CONN_INTERVAL:
+      return true;
+    default:
+      break;
+  }
+  return false;
+}
+
 void acl_disconnect_after_role_switch(uint16_t conn_handle, tHCI_STATUS reason,
                                       std::string comment) {
+  if (!is_disconnect_reason_valid(reason)) {
+    LOG_WARN(
+        "Controller will not accept invalid reason parameter:%s"
+        " instead sending:%s",
+        hci_error_code_text(reason).c_str(),
+        hci_error_code_text(HCI_ERR_PEER_USER).c_str());
+    reason = HCI_ERR_PEER_USER;
+  }
+
   tACL_CONN* p_acl = internal_.acl_get_connection_from_handle(conn_handle);
   if (p_acl == nullptr) {
     LOG_ERROR("Sending disconnect for unknown acl:%hu PLEASE FIX", conn_handle);
diff --git a/system/stack/test/btm/stack_btm_test.cc b/system/stack/test/btm/stack_btm_test.cc
index 829b714ef1cce024e2a43e6ee5c74824fb115ae9..3ec8fb58afe92d85ddf1bb866ae323905e6d43f2 100644
--- a/system/stack/test/btm/stack_btm_test.cc
+++ b/system/stack/test/btm/stack_btm_test.cc
@@ -493,3 +493,23 @@ TEST_F(StackBtmWithInitFreeTest, wipe_secrets_and_remove) {
 
   wipe_secrets_and_remove(device_record);
 }
+
+bool is_disconnect_reason_valid(const tHCI_REASON& reason);
+TEST_F(StackBtmWithInitFreeTest, is_disconnect_reason_valid) {
+  std::set<tHCI_REASON> valid_reason_set{
+      HCI_ERR_AUTH_FAILURE,
+      HCI_ERR_PEER_USER,
+      HCI_ERR_REMOTE_LOW_RESOURCE,
+      HCI_ERR_REMOTE_POWER_OFF,
+      HCI_ERR_UNSUPPORTED_REM_FEATURE,
+      HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED,
+      HCI_ERR_UNACCEPT_CONN_INTERVAL,
+  };
+  for (unsigned u = 0; u < 256; u++) {
+    const tHCI_REASON reason = static_cast<tHCI_REASON>(u);
+    if (valid_reason_set.count(reason))
+      ASSERT_TRUE(is_disconnect_reason_valid(reason));
+    else
+      ASSERT_FALSE(is_disconnect_reason_valid(reason));
+  }
+}