diff --git a/frontend/src/components/Modals/MangeWorkspace/Upload/FileUploadProgress/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Upload/FileUploadProgress/index.jsx
index 8c5054c30a0aacc4931599e61a21d42fe3ad44d6..5883c4b2095e89745d951c877ef72bc7805a974f 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Upload/FileUploadProgress/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Upload/FileUploadProgress/index.jsx
@@ -10,6 +10,8 @@ function FileUploadProgressComponent({
   file,
   rejected = false,
   reason = null,
+  onUploadSuccess,
+  onUploadError,
 }) {
   const [timerMs, setTimerMs] = useState(10);
   const [status, setStatus] = useState(file?.rejected ? "uploading" : "failed");
@@ -24,9 +26,16 @@ function FileUploadProgressComponent({
       }, 100);
 
       // Chunk streaming not working in production so we just sit and wait
-      await Workspace.uploadFile(slug, formData);
-      setStatus("complete");
-      clearInterval(timer);
+      const { response, data } = await Workspace.uploadFile(slug, formData);
+      if (!response.ok) {
+        setStatus("failed");
+        clearInterval(timer);
+        onUploadError(data.error);
+      } else {
+        setStatus("complete");
+        clearInterval(timer);
+        onUploadSuccess();
+      }
     }
     !!file && !rejected && uploadFile();
   }, []);
diff --git a/frontend/src/components/Modals/MangeWorkspace/Upload/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Upload/index.jsx
index 2f56dba7d3e42aa79bc8cf2794df8be3b13c909e..b7a8bc37c421750078cc0614dce9c95fdd573c5b 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Upload/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Upload/index.jsx
@@ -10,6 +10,19 @@ import { Frown } from "react-feather";
 export default function UploadToWorkspace({ workspace, fileTypes }) {
   const [ready, setReady] = useState(null);
   const [files, setFiles] = useState([]);
+  const [successMsg, setSuccessMsg] = useState("");
+  const [errorMsg, setErrorMsg] = useState("");
+
+  const handleUploadSuccess = () => {
+    setSuccessMsg("File uploaded successfully");
+    setErrorMsg(null);
+  };
+
+  const handleUploadError = (message) => {
+    setErrorMsg(`Upload failed: ${message}`);
+    setSuccessMsg(null);
+  };
+
   const onDrop = useCallback(async (acceptedFiles, rejections) => {
     const newAccepted = acceptedFiles.map((file) => {
       return {
@@ -37,6 +50,20 @@ export default function UploadToWorkspace({ workspace, fileTypes }) {
     checkProcessorOnline();
   }, []);
 
+  useEffect(() => {
+    if (!!successMsg) {
+      setTimeout(() => {
+        setSuccessMsg("");
+      }, 3_500);
+    }
+
+    if (!!errorMsg) {
+      setTimeout(() => {
+        setErrorMsg("");
+      }, 3_500);
+    }
+  }, [successMsg, errorMsg]);
+
   const { getRootProps, getInputProps } = useDropzone({
     onDrop,
     accept: {
@@ -133,6 +160,8 @@ export default function UploadToWorkspace({ workspace, fileTypes }) {
                 slug={workspace.slug}
                 rejected={file?.rejected}
                 reason={file?.reason}
+                onUploadSuccess={handleUploadSuccess}
+                onUploadError={handleUploadError}
               />
             ))}
           </div>
@@ -144,6 +173,16 @@ export default function UploadToWorkspace({ workspace, fileTypes }) {
           {Object.values(fileTypes).flat().join(" ")}
         </code>
       </p>
+      {successMsg && (
+        <p className="text-green-600 dark:text-green-400 text-sm text-center pt-2">
+          {successMsg}
+        </p>
+      )}
+      {errorMsg && (
+        <p className="text-red-600 dark:text-red-400 text-sm text-center pt-2">
+          {errorMsg}
+        </p>
+      )}
     </ModalWrapper>
   );
 }
diff --git a/frontend/src/models/workspace.js b/frontend/src/models/workspace.js
index ac61c71863a3932d81ad307fa5c31143265e765a..540a6f134897e222dc28686524bcd4e8a5d86be2 100644
--- a/frontend/src/models/workspace.js
+++ b/frontend/src/models/workspace.js
@@ -107,7 +107,9 @@ const Workspace = {
       body: formData,
       headers: baseHeaders(),
     });
-    return response;
+
+    const data = await response.json();
+    return { response, data };
   },
 };
 
diff --git a/server/endpoints/workspaces.js b/server/endpoints/workspaces.js
index c1b468fbd61ccf766cd1ec0ccec8c694d3989c7c..ff8e2aeab546d249c1e6cf53ddde99b3bc2fd6d3 100644
--- a/server/endpoints/workspaces.js
+++ b/server/endpoints/workspaces.js
@@ -6,9 +6,6 @@ const { WorkspaceChats } = require("../models/workspaceChats");
 const { convertToChatHistory } = require("../utils/chats");
 const { getVectorDbClass } = require("../utils/helpers");
 const { setupMulter } = require("../utils/files/multer");
-const {
-  fileUploadProgress,
-} = require("../utils/middleware/fileUploadProgress");
 const {
   checkPythonAppAlive,
   processDocument,
@@ -69,32 +66,31 @@ function workspaceEndpoints(app) {
 
   app.post(
     "/workspace/:slug/upload",
-    fileUploadProgress,
     handleUploads.single("file"),
-    async function (request, _) {
+    async function (request, response) {
       const { originalname } = request.file;
       const processingOnline = await checkPythonAppAlive();
 
       if (!processingOnline) {
-        console.log(
-          `Python processing API is not online. Document ${originalname} will not be processed automatically.`
-        );
-        return;
+        response
+          .status(500)
+          .json({
+            success: false,
+            error: `Python processing API is not online. Document ${originalname} will not be processed automatically.`,
+          })
+          .end();
       }
 
       const { success, reason } = await processDocument(originalname);
       if (!success) {
-        console.log(
-          `Python processing API was not able to process document ${originalname}. Reason: ${reason}`
-        );
-        return false;
+        response.status(500).json({ success: false, error: reason }).end();
       }
 
       console.log(
         `Document ${originalname} uploaded processed and successfully. It is now available in documents.`
       );
       await Telemetry.sendTelemetry("document_uploaded");
-      return;
+      response.status(200).json({ success: true, error: null });
     }
   );
 
diff --git a/server/utils/middleware/fileUploadProgress.js b/server/utils/middleware/fileUploadProgress.js
deleted file mode 100644
index ecacfd5e015b79af201ead2930524da38c96bc70..0000000000000000000000000000000000000000
--- a/server/utils/middleware/fileUploadProgress.js
+++ /dev/null
@@ -1,26 +0,0 @@
-async function fileUploadProgress(request, response, next) {
-  let progress = 0;
-  const fileSize = request.headers["content-length"]
-    ? parseInt(request.headers["content-length"])
-    : 0;
-
-  // Note(tcarambat): While this is chunked it does not stream back to the UI for some reason.
-  // It just waits for the entire requests to finish. Likely because it is not using EventSource on frontend
-  // which is limited to GET.
-  // TODO: Someone smarter than me add streaming here to report back real-time progress.
-  response.writeHead(200);
-  request.on("data", (chunk) => {
-    progress += chunk.length;
-    const percentage = (progress / fileSize) * 100;
-    response.write(`${JSON.stringify({ progress, fileSize, percentage })}\n`);
-    if (progress >= fileSize) {
-      response.end();
-    }
-  });
-
-  next();
-}
-
-module.exports = {
-  fileUploadProgress,
-};