diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js
--- a/web/input/input-state-container.react.js
+++ b/web/input/input-state-container.react.js
@@ -43,7 +43,10 @@
 import { useNewThickThread } from 'lib/hooks/thread-hooks.js';
 import { useLegacyAshoatKeyserverCall } from 'lib/keyserver-conn/legacy-keyserver-call.js';
 import { getNextLocalUploadID } from 'lib/media/media-utils.js';
-import { pendingToRealizedThreadIDsSelector } from 'lib/selectors/thread-selectors.js';
+import {
+  threadInfoSelector,
+  pendingToRealizedThreadIDsSelector,
+} from 'lib/selectors/thread-selectors.js';
 import {
   dmOperationSpecificationTypes,
   type OutboundDMOperationSpecification,
@@ -142,7 +145,7 @@
 };
 type Props = {
   ...BaseProps,
-  +activeChatThreadID: ?string,
+  +activeChatThreadInfo: ?ThreadInfo,
   +drafts: { +[key: string]: string },
   +viewerID: ?string,
   +messageStoreMessages: { +[id: string]: RawMessageInfo },
@@ -613,17 +616,21 @@
     return threadCreationPromise;
   }
 
-  inputBaseStateSelector: (?string) => PropsAndState => BaseInputState =
-    _memoize((threadID: ?string) =>
+  inputBaseStateSelector: (?ThreadInfo) => PropsAndState => BaseInputState =
+    _memoize((activeThreadInfo: ?ThreadInfo) =>
       createSelector(
         (propsAndState: PropsAndState) =>
-          threadID ? propsAndState.pendingUploads[threadID] : null,
+          activeThreadInfo
+            ? propsAndState.pendingUploads[activeThreadInfo.id]
+            : null,
         (propsAndState: PropsAndState) =>
-          threadID
-            ? propsAndState.drafts[draftKeyFromThreadID(threadID)]
+          activeThreadInfo
+            ? propsAndState.drafts[draftKeyFromThreadID(activeThreadInfo.id)]
             : null,
         (propsAndState: PropsAndState) =>
-          threadID ? propsAndState.textCursorPositions[threadID] : null,
+          activeThreadInfo
+            ? propsAndState.textCursorPositions[activeThreadInfo.id]
+            : null,
         (
           pendingUploads: ?{ [localUploadID: string]: PendingMultimediaUpload },
           draft: ?string,
@@ -648,6 +655,7 @@
               ];
             }
           }
+          const threadID = activeThreadInfo?.id;
           return ({
             pendingUploads: threadPendingUploads,
             assignedUploads,
@@ -658,7 +666,7 @@
               files: $ReadOnlyArray<File>,
             ) => this.appendFiles(threadInfo, files),
             cancelPendingUpload: (localUploadID: string) =>
-              this.cancelPendingUpload(threadID, localUploadID),
+              this.cancelPendingUpload(activeThreadInfo, localUploadID),
             sendTextMessage: (
               messageInfo: RawTextMessageInfo,
               threadInfo: ThreadInfo,
@@ -1211,12 +1219,13 @@
     this.props.dispatch({ type: queueReportsActionType, payload: { reports } });
   }
 
-  cancelPendingUpload(threadID: ?string, localUploadID: string) {
-    invariant(threadID, 'threadID should be set in cancelPendingUpload');
+  cancelPendingUpload(threadInfo: ?ThreadInfo, localUploadID: string) {
+    invariant(threadInfo, 'threadID should be set in cancelPendingUpload');
 
     let revokeURL: ?string, abortRequest: ?() => void;
     this.setState(
       prevState => {
+        const threadID = threadInfo.id;
         const newThreadID = this.getRealizedOrPendingThreadID(threadID);
         const currentPendingUploads = prevState.pendingUploads[newThreadID];
         if (!currentPendingUploads) {
@@ -1233,10 +1242,13 @@
           abortRequest = pendingUpload.abort;
         }
         if (pendingUpload.serverID) {
-          void this.props.deleteUpload({
-            id: pendingUpload.serverID,
-            keyserverOrThreadID: threadID,
-          });
+          const { serverID } = pendingUpload;
+          if (!threadTypeIsThick(threadInfo.type)) {
+            void this.props.deleteUpload({
+              id: serverID,
+              keyserverOrThreadID: threadID,
+            });
+          }
           if (isBlobServiceURI(pendingUpload.uri)) {
             const identityContext = this.props.identityContext;
             invariant(identityContext, 'Identity context should be set');
@@ -1684,11 +1696,11 @@
   };
 
   render(): React.Node {
-    const { activeChatThreadID } = this.props;
+    const { activeChatThreadInfo } = this.props;
 
     // we're going with two selectors as we want to avoid
     // recreation of chat state setter functions on typeahead state updates
-    const inputBaseState = this.inputBaseStateSelector(activeChatThreadID)({
+    const inputBaseState = this.inputBaseStateSelector(activeChatThreadInfo)({
       ...this.state,
       ...this.props,
     });
@@ -1716,6 +1728,9 @@
     const activeChatThreadID = useSelector(
       state => state.navInfo.activeChatThreadID,
     );
+    const activeChatThreadInfo = useSelector(state =>
+      activeChatThreadID ? threadInfoSelector(state)[activeChatThreadID] : null,
+    );
     const drafts = useSelector(state => state.draftStore.drafts);
     const viewerID = useSelector(
       state => state.currentUserInfo && state.currentUserInfo.id,
@@ -1760,7 +1775,7 @@
     return (
       <InputStateContainer
         {...props}
-        activeChatThreadID={activeChatThreadID}
+        activeChatThreadInfo={activeChatThreadInfo}
         drafts={drafts}
         viewerID={viewerID}
         messageStoreMessages={messageStoreMessages}