diff --git a/CHANGELOG.md b/CHANGELOG.md
index a14be9e3..72a54920 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@
 
 ## Unreleased
 
+### Added
+
+- Added functionality to show setup script error message to the end user.
+
 ### Fixed
 
 - Fix bug where wildcard configs would not be written under certain conditions.
diff --git a/src/main/kotlin/com/coder/gateway/CoderGatewayConstants.kt b/src/main/kotlin/com/coder/gateway/CoderGatewayConstants.kt
index 6344aca6..1defb91d 100644
--- a/src/main/kotlin/com/coder/gateway/CoderGatewayConstants.kt
+++ b/src/main/kotlin/com/coder/gateway/CoderGatewayConstants.kt
@@ -3,4 +3,5 @@ package com.coder.gateway
 object CoderGatewayConstants {
     const val GATEWAY_CONNECTOR_ID = "Coder.Gateway.Connector"
     const val GATEWAY_RECENT_CONNECTIONS_ID = "Coder.Gateway.Recent.Connections"
+    const val GATEWAY_SETUP_COMMAND_ERROR = "CODER_SETUP_ERROR"
 }
diff --git a/src/main/kotlin/com/coder/gateway/CoderRemoteConnectionHandle.kt b/src/main/kotlin/com/coder/gateway/CoderRemoteConnectionHandle.kt
index 102b73fc..790a2cd3 100644
--- a/src/main/kotlin/com/coder/gateway/CoderRemoteConnectionHandle.kt
+++ b/src/main/kotlin/com/coder/gateway/CoderRemoteConnectionHandle.kt
@@ -2,6 +2,7 @@
 
 package com.coder.gateway
 
+import com.coder.gateway.CoderGatewayConstants.GATEWAY_SETUP_COMMAND_ERROR
 import com.coder.gateway.cli.CoderCLIManager
 import com.coder.gateway.models.WorkspaceProjectIDE
 import com.coder.gateway.models.toIdeWithStatus
@@ -160,25 +161,38 @@ class CoderRemoteConnectionHandle {
                 )
                 logger.info("Adding ${parameters.ideName} for ${parameters.hostname}:${parameters.projectPath} to recent connections")
                 recentConnectionsService.addRecentConnection(parameters.toRecentWorkspaceConnection())
+            } catch (e: CoderSetupCommandException) {
+                logger.error("Failed to run setup command", e)
+                showConnectionErrorMessage(
+                    e.message ?: "Unknown error",
+                    "gateway.connector.coder.setup-command.failed",
+                )
             } catch (e: Exception) {
                 if (isCancellation(e)) {
                     logger.info("Connection canceled due to ${e.javaClass.simpleName}")
                 } else {
                     logger.error("Failed to connect (will not retry)", e)
-                    // The dialog will close once we return so write the error
-                    // out into a new dialog.
-                    ApplicationManager.getApplication().invokeAndWait {
-                        Messages.showMessageDialog(
-                            e.message ?: e.javaClass.simpleName ?: "Aborted",
-                            CoderGatewayBundle.message("gateway.connector.coder.connection.failed"),
-                            Messages.getErrorIcon(),
-                        )
-                    }
+                    showConnectionErrorMessage(
+                        e.message ?: e.javaClass.simpleName ?: "Aborted",
+                        "gateway.connector.coder.connection.failed"
+                    )
                 }
             }
         }
     }
 
+    // The dialog will close once we return so write the error
+    // out into a new dialog.
+    private fun showConnectionErrorMessage(message: String, titleKey: String) {
+        ApplicationManager.getApplication().invokeAndWait {
+            Messages.showMessageDialog(
+                message,
+                CoderGatewayBundle.message(titleKey),
+                Messages.getErrorIcon(),
+            )
+        }
+    }
+
     /**
      * Return a new (non-EAP) IDE if we should update.
      */
@@ -412,18 +426,15 @@ class CoderRemoteConnectionHandle {
     ) {
         if (setupCommand.isNotBlank()) {
             indicator.text = "Running setup command..."
-            try {
+            processSetupCommand(ignoreSetupFailure) {
                 exec(workspace, setupCommand)
-            } catch (ex: Exception) {
-                if (!ignoreSetupFailure) {
-                    throw ex
-                }
             }
         } else {
             logger.info("No setup command to run on ${workspace.hostname}")
         }
     }
 
+
     /**
      * Execute a command in the IDE's bin directory.
      * This exists since the accessor does not provide a generic exec.
@@ -523,5 +534,26 @@ class CoderRemoteConnectionHandle {
 
     companion object {
         val logger = Logger.getInstance(CoderRemoteConnectionHandle::class.java.simpleName)
+        @Throws(CoderSetupCommandException::class)
+        fun processSetupCommand(
+            ignoreSetupFailure: Boolean,
+            execCommand: () -> String
+        ) {
+            try {
+                val errorText = execCommand
+                    .invoke()
+                    .lines()
+                    .firstOrNull { it.contains(GATEWAY_SETUP_COMMAND_ERROR) }
+                    ?.let { it.substring(it.indexOf(GATEWAY_SETUP_COMMAND_ERROR) + GATEWAY_SETUP_COMMAND_ERROR.length).trim() }
+
+                if (!errorText.isNullOrBlank()) {
+                    throw CoderSetupCommandException(errorText)
+                }
+            } catch (ex: Exception) {
+                if (!ignoreSetupFailure) {
+                    throw CoderSetupCommandException(ex.message ?: "Unknown error", ex)
+                }
+            }
+        }
     }
 }
diff --git a/src/main/kotlin/com/coder/gateway/CoderSetupCommandException.kt b/src/main/kotlin/com/coder/gateway/CoderSetupCommandException.kt
new file mode 100644
index 00000000..e43d9269
--- /dev/null
+++ b/src/main/kotlin/com/coder/gateway/CoderSetupCommandException.kt
@@ -0,0 +1,7 @@
+package com.coder.gateway
+
+class CoderSetupCommandException : Exception {
+
+    constructor(message: String) : super(message)
+    constructor(message: String, cause: Throwable) : super(message, cause)
+}
\ No newline at end of file
diff --git a/src/main/resources/messages/CoderGatewayBundle.properties b/src/main/resources/messages/CoderGatewayBundle.properties
index 4400eb89..f318012e 100644
--- a/src/main/resources/messages/CoderGatewayBundle.properties
+++ b/src/main/resources/messages/CoderGatewayBundle.properties
@@ -49,6 +49,7 @@ gateway.connector.coder.connection.provider.title=Connecting to Coder workspace.
 gateway.connector.coder.connecting=Connecting...
 gateway.connector.coder.connecting.retry=Connecting (attempt {0})...
 gateway.connector.coder.connection.failed=Failed to connect
+gateway.connector.coder.setup-command.failed=Failed to set up backend IDE
 gateway.connector.coder.connecting.failed.retry=Failed to connect...retrying {0}
 gateway.connector.settings.data-directory.title=Data directory
 gateway.connector.settings.data-directory.comment=Directories are created \
diff --git a/src/test/kotlin/com/coder/gateway/util/SetupCommandTest.kt b/src/test/kotlin/com/coder/gateway/util/SetupCommandTest.kt
new file mode 100644
index 00000000..b237925b
--- /dev/null
+++ b/src/test/kotlin/com/coder/gateway/util/SetupCommandTest.kt
@@ -0,0 +1,48 @@
+package com.coder.gateway.util
+
+import com.coder.gateway.CoderRemoteConnectionHandle.Companion.processSetupCommand
+import com.coder.gateway.CoderSetupCommandException
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.assertThrows
+import kotlin.test.assertEquals
+
+internal class SetupCommandTest {
+
+    @Test
+    fun executionErrors() {
+        assertEquals(
+            "Execution error",
+            assertThrows<CoderSetupCommandException> {
+                processSetupCommand(false) { throw Exception("Execution error") }
+            }.message
+        )
+        processSetupCommand(true) { throw Exception("Execution error") }
+    }
+
+    @Test
+    fun setupScriptError() {
+        assertEquals(
+            "Your IDE is expired, please update",
+            assertThrows<CoderSetupCommandException> {
+                processSetupCommand(false) {
+                    """
+                execution line 1    
+                execution line 2
+                CODER_SETUP_ERRORYour IDE is expired, please update
+                execution line 3    
+                """
+                }
+            }.message
+        )
+
+        processSetupCommand(true) {
+            """
+                execution line 1    
+                execution line 2
+                CODER_SETUP_ERRORYour IDE is expired, please update
+                execution line 3    
+                """
+        }
+
+    }
+}
\ No newline at end of file