Skip to content

Commit d5fddf4

Browse files
authored
fix: agent error reporting and handling (#93)
- if workspace or agent start with error, we report the workspace as started with errors and highlight the text with red. - the workspace is still marked as reachable even though it is unhealthy but we no longer connect automatically to the workspace via ssh when user selects the workspace from the env list.
1 parent ec7753b commit d5fddf4

File tree

3 files changed

+17
-15
lines changed

3 files changed

+17
-15
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66

77
- support for using proxies. Proxy authentication is not yet supported.
88

9+
### Changed
10+
11+
- connections to the workspace are no longer established automatically after agent started with error.
12+
913
## 0.1.5 - 2025-04-14
1014

1115
### Fixed

src/main/kotlin/com/coder/toolbox/models/WorkspaceAndAgentStatus.kt

+11-13
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,16 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
6161
fun toRemoteEnvironmentState(context: CoderToolboxContext): CustomRemoteEnvironmentState {
6262
return CustomRemoteEnvironmentState(
6363
label,
64-
getStateColor(context),
65-
ready(), // reachable
64+
color = getStateColor(context),
65+
reachable = ready() || unhealthy(),
6666
// TODO@JB: How does this work? Would like a spinner for pending states.
67-
getStateIcon()
67+
icon = getStateIcon()
6868
)
6969
}
7070

7171
private fun getStateColor(context: CoderToolboxContext): StateColor {
7272
return if (ready()) context.envStateColorPalette.getColor(StandardRemoteEnvironmentState.Active)
73+
else if (unhealthy()) context.envStateColorPalette.getColor(StandardRemoteEnvironmentState.Unhealthy)
7374
else if (canStart()) context.envStateColorPalette.getColor(StandardRemoteEnvironmentState.Failed)
7475
else if (pending()) context.envStateColorPalette.getColor(StandardRemoteEnvironmentState.Activating)
7576
else if (this == DELETING) context.envStateColorPalette.getColor(StandardRemoteEnvironmentState.Deleting)
@@ -78,7 +79,7 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
7879
}
7980

8081
private fun getStateIcon(): EnvironmentStateIcons {
81-
return if (ready()) EnvironmentStateIcons.Active
82+
return if (ready() || unhealthy()) EnvironmentStateIcons.Active
8283
else if (canStart()) EnvironmentStateIcons.Hibernated
8384
else if (pending()) EnvironmentStateIcons.Connecting
8485
else if (this == DELETING || this == DELETED) EnvironmentStateIcons.Offline
@@ -88,13 +89,10 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
8889
/**
8990
* Return true if the agent is in a connectable state.
9091
*/
91-
fun ready(): Boolean {
92-
// It seems that the agent can get stuck in a `created` state if the
93-
// workspace is updated and the agent is restarted (presumably because
94-
// lifecycle scripts are not running again). This feels like either a
95-
// Coder or template bug, but `coder ssh` and the VS Code plugin will
96-
// still connect so do the same here to not be the odd one out.
97-
return listOf(READY, START_ERROR, AGENT_STARTING_READY, START_TIMEOUT_READY, CREATED)
92+
fun ready(): Boolean = this == READY
93+
94+
fun unhealthy(): Boolean {
95+
return listOf(START_ERROR, START_TIMEOUT_READY)
9896
.contains(this)
9997
}
10098

@@ -103,7 +101,7 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
103101
*/
104102
fun pending(): Boolean {
105103
// See ready() for why `CREATED` is not in this list.
106-
return listOf(CONNECTING, TIMEOUT, AGENT_STARTING, START_TIMEOUT, QUEUED, STARTING)
104+
return listOf(CREATED, CONNECTING, TIMEOUT, AGENT_STARTING, START_TIMEOUT, QUEUED, STARTING)
107105
.contains(this)
108106
}
109107

@@ -116,7 +114,7 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
116114
/**
117115
* Return true if the workspace can be stopped.
118116
*/
119-
fun canStop(): Boolean = ready() || pending()
117+
fun canStop(): Boolean = ready() || pending() || unhealthy()
120118

121119
// We want to check that the workspace is `running`, the agent is
122120
// `connected`, and the agent lifecycle state is `ready` to ensure the best

src/main/kotlin/com/coder/toolbox/util/CoderProtocolHandler.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ open class CoderProtocolHandler(
144144
val status = WorkspaceAndAgentStatus.from(workspace, agent)
145145

146146
if (!status.ready()) {
147-
context.logger.error("Agent ${agent.name} for workspace $workspaceName from $deploymentURL is not started")
148-
context.showErrorPopup(MissingArgumentException("Can't handle URI because agent ${agent.name} for workspace $workspaceName from $deploymentURL is not started"))
147+
context.logger.error("Agent ${agent.name} for workspace $workspaceName from $deploymentURL is not ready")
148+
context.showErrorPopup(MissingArgumentException("Can't handle URI because agent ${agent.name} for workspace $workspaceName from $deploymentURL is not ready"))
149149
return
150150
}
151151

0 commit comments

Comments
 (0)