diff --git a/keyserver/src/updaters/thread-updaters.js b/keyserver/src/updaters/thread-updaters.js
--- a/keyserver/src/updaters/thread-updaters.js
+++ b/keyserver/src/updaters/thread-updaters.js
@@ -146,6 +146,7 @@
     time: Date.now(),
     userIDs: memberIDs,
     newRole: request.role,
+    roleName: threadInfo.roles[request.role].name,
   };
   const newMessageInfos = await createMessages(viewer, [messageData]);
 
diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js
--- a/lib/shared/message-utils.js
+++ b/lib/shared/message-utils.js
@@ -44,6 +44,7 @@
 import type { UserInfos } from '../types/user-types.js';
 import {
   type EntityText,
+  ET,
   useEntityTextAsString,
 } from '../utils/entity-text.js';
 
@@ -624,6 +625,17 @@
   return item;
 }
 
+function constructChangeRoleEntityText(
+  affectedUsers: EntityText | string,
+  roleName: ?string,
+): EntityText {
+  if (!roleName) {
+    return ET`assigned ${affectedUsers} a new role`;
+  }
+
+  return ET`assigned ${affectedUsers} the "${roleName}" role`;
+}
+
 export {
   localIDPrefix,
   messageKey,
@@ -651,4 +663,5 @@
   useMessageCreationSideEffectsFunc,
   getPinnedContentFromMessage,
   modifyItemForResultScreen,
+  constructChangeRoleEntityText,
 };
diff --git a/lib/shared/messages/change-role-message-spec.js b/lib/shared/messages/change-role-message-spec.js
--- a/lib/shared/messages/change-role-message-spec.js
+++ b/lib/shared/messages/change-role-message-spec.js
@@ -9,6 +9,7 @@
   type RobotextParams,
 } from './message-spec.js';
 import { joinResult } from './utils.js';
+import type { PlatformDetails } from '../../types/device-types.js';
 import { messageTypes } from '../../types/message-types-enum.js';
 import type {
   MessageInfo,
@@ -20,6 +21,7 @@
   type RawChangeRoleMessageInfo,
   rawChangeRoleMessageInfoValidator,
 } from '../../types/messages/change-role.js';
+import type { RawUnsupportedMessageInfo } from '../../types/messages/unsupported';
 import type { NotifTexts } from '../../types/notif-types.js';
 import type { ThreadInfo } from '../../types/thread-types.js';
 import type { RelativeUserInfo } from '../../types/user-types.js';
@@ -28,8 +30,11 @@
   type EntityText,
   pluralizeEntityText,
 } from '../../utils/entity-text.js';
+import { entityTextToRawString } from '../../utils/entity-text.js';
 import { values } from '../../utils/objects.js';
+import { constructChangeRoleEntityText } from '../message-utils.js';
 import { notifRobotextForMessageInfo } from '../notif-utils.js';
+import { NEXT_CODE_VERSION, hasMinCodeVersion } from '../version-utils.js';
 
 export const changeRoleMessageSpec: MessageSpec<
   ChangeRoleMessageData,
@@ -42,6 +47,7 @@
     return JSON.stringify({
       userIDs: data.userIDs,
       newRole: data.newRole,
+      roleName: data.roleName,
     });
   },
 
@@ -59,6 +65,7 @@
       creatorID: row.creatorID.toString(),
       userIDs: content.userIDs,
       newRole: content.newRole,
+      roleName: content.roleName,
     };
   },
 
@@ -79,6 +86,7 @@
       creatorID: clientDBMessageInfo.user,
       userIDs: content.userIDs,
       newRole: content.newRole,
+      roleName: content.roleName,
     };
     return rawChangeRoleMessageInfo;
   },
@@ -97,6 +105,7 @@
       time: rawMessageInfo.time,
       members,
       newRole: rawMessageInfo.newRole,
+      roleName: rawMessageInfo.roleName,
     };
   },
 
@@ -122,9 +131,18 @@
 
     const { threadInfo } = params;
     invariant(threadInfo, 'ThreadInfo should be set for CHANGE_ROLE message');
-    const roleName = threadInfo.roles[messageInfo.newRole].name;
 
-    return ET`${creator} assigned ${affectedUsers} the \"${roleName}\" role`;
+    const threadRoleName = threadInfo.roles[messageInfo.newRole]?.name;
+    const messageInfoRoleName = messageInfo.roleName;
+
+    const roleName = threadRoleName ?? messageInfoRoleName;
+
+    const constructedEntityText = constructChangeRoleEntityText(
+      affectedUsers,
+      roleName,
+    );
+
+    return ET`${creator} ${constructedEntityText}`;
   },
 
   async notificationTexts(
@@ -162,6 +180,43 @@
     };
   },
 
+  shimUnsupportedMessageInfo(
+    rawMessageInfo: RawChangeRoleMessageInfo,
+    platformDetails: ?PlatformDetails,
+  ): RawChangeRoleMessageInfo | RawUnsupportedMessageInfo {
+    if (hasMinCodeVersion(platformDetails, { native: NEXT_CODE_VERSION })) {
+      return rawMessageInfo;
+    }
+
+    const { id, userIDs } = rawMessageInfo;
+    invariant(id !== null && id !== undefined, 'id should be set on server');
+
+    const affectedUsers = userIDs.length === 1 ? 'a member' : 'some members';
+    const roleName = rawMessageInfo.roleName;
+
+    const constructedEntityText = constructChangeRoleEntityText(
+      affectedUsers,
+      roleName,
+    );
+    const stringifiedEntityText = entityTextToRawString(constructedEntityText);
+
+    return {
+      type: messageTypes.UNSUPPORTED,
+      id,
+      threadID: rawMessageInfo.threadID,
+      creatorID: rawMessageInfo.creatorID,
+      time: rawMessageInfo.time,
+      robotext: stringifiedEntityText,
+      unsupportedMessageInfo: rawMessageInfo,
+    };
+  },
+
+  unshimMessageInfo(
+    unwrapped: RawChangeRoleMessageInfo,
+  ): RawChangeRoleMessageInfo {
+    return unwrapped;
+  },
+
   notificationCollapseKey(rawMessageInfo: RawChangeRoleMessageInfo): string {
     return joinResult(
       rawMessageInfo.type,
diff --git a/lib/types/messages/change-role.js b/lib/types/messages/change-role.js
--- a/lib/types/messages/change-role.js
+++ b/lib/types/messages/change-role.js
@@ -7,17 +7,18 @@
 import type { RelativeUserInfo } from '../user-types.js';
 
 export type ChangeRoleMessageData = {
-  type: 6,
-  threadID: string,
-  creatorID: string,
-  time: number,
-  userIDs: string[],
-  newRole: string,
+  +type: 6,
+  +threadID: string,
+  +creatorID: string,
+  +time: number,
+  +userIDs: string[],
+  +newRole: string,
+  +roleName?: string, // Older clients will not have this field
 };
 
 export type RawChangeRoleMessageInfo = {
   ...ChangeRoleMessageData,
-  id: string,
+  +id: string,
 };
 
 export const rawChangeRoleMessageInfoValidator: TInterface<RawChangeRoleMessageInfo> =
@@ -29,14 +30,16 @@
     userIDs: t.list(t.String),
     newRole: tID,
     id: tID,
+    roleName: t.maybe(t.String),
   });
 
 export type ChangeRoleMessageInfo = {
-  type: 6,
-  id: string,
-  threadID: string,
-  creator: RelativeUserInfo,
-  time: number,
-  members: RelativeUserInfo[],
-  newRole: string,
+  +type: 6,
+  +id: string,
+  +threadID: string,
+  +creator: RelativeUserInfo,
+  +time: number,
+  +members: RelativeUserInfo[],
+  +newRole: string,
+  +roleName?: string, // Older clients will not have this field
 };