From 4efc08aa170e0b7e77837851b107e5449d92ae90 Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Sun, 31 May 2026 22:44:31 +0000 Subject: [PATCH 1/2] fix(registry): check rows.Err() after iteration in provisiontimeout + healthsweep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds rows.Err() checks after Next() loops in: - registry/provisiontimeout.go (provisioning timeout candidate scan) - registry/healthsweep.go sweepOnlineWorkspaces (local container check) - registry/healthsweep.go sweepStaleRemoteWorkspaces (external heartbeat check) Also fixes silently ignored rows.Scan errors in all three loops — previously a scan failure would drop the row silently instead of logging the error. Prevents silently skipping workspaces during timeout/health sweeps when the DB connection fails mid-iteration or a row contains unexpected data. --- .../internal/registry/healthsweep.go | 18 ++++++++++++++---- .../internal/registry/provisiontimeout.go | 9 +++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/workspace-server/internal/registry/healthsweep.go b/workspace-server/internal/registry/healthsweep.go index fdeef4f96..09e67e883 100644 --- a/workspace-server/internal/registry/healthsweep.go +++ b/workspace-server/internal/registry/healthsweep.go @@ -89,9 +89,14 @@ func sweepOnlineWorkspaces(ctx context.Context, checker ContainerChecker, onOffl var ids []string for rows.Next() { var id string - if err := rows.Scan(&id); err == nil { - ids = append(ids, id) + if err := rows.Scan(&id); err != nil { + log.Printf("Health sweep: scan error: %v", err) + continue } + ids = append(ids, id) + } + if err := rows.Err(); err != nil { + log.Printf("Health sweep: rows error: %v", err) } for _, id := range ids { @@ -155,9 +160,14 @@ func sweepStaleRemoteWorkspaces(ctx context.Context, onOffline OfflineHandler) { var ids []string for rows.Next() { var id string - if err := rows.Scan(&id); err == nil { - ids = append(ids, id) + if err := rows.Scan(&id); err != nil { + log.Printf("Health sweep (remote): scan error: %v", err) + continue } + ids = append(ids, id) + } + if err := rows.Err(); err != nil { + log.Printf("Health sweep (remote): rows error: %v", err) } for _, id := range ids { diff --git a/workspace-server/internal/registry/provisiontimeout.go b/workspace-server/internal/registry/provisiontimeout.go index 46b9e1577..37e9b8b6d 100644 --- a/workspace-server/internal/registry/provisiontimeout.go +++ b/workspace-server/internal/registry/provisiontimeout.go @@ -162,9 +162,14 @@ func sweepStuckProvisioning(ctx context.Context, emitter ProvisionTimeoutEmitter var ids []candidate for rows.Next() { var c candidate - if err := rows.Scan(&c.id, &c.runtime, &c.ageSec); err == nil { - ids = append(ids, c) + if err := rows.Scan(&c.id, &c.runtime, &c.ageSec); err != nil { + log.Printf("Provision timeout: scan error: %v", err) + continue } + ids = append(ids, c) + } + if err := rows.Err(); err != nil { + log.Printf("Provision timeout: rows error: %v", err) } for _, c := range ids { -- 2.52.0 From 88a538117e7d610a50e9023fe322205b75b402a9 Mon Sep 17 00:00:00 2001 From: "Molecule AI Dev Engineer A (Kimi)" Date: Mon, 1 Jun 2026 12:36:44 +0000 Subject: [PATCH 2/2] ci: remove unused canvasUserMessage type to fix lint on staging internal/handlers/a2a_proxy_helpers.go:412 had an unused struct that causes golangci-lint `unused` failure on every PR targeting staging. Co-Authored-By: Claude Opus 4.7 --- workspace-server/internal/handlers/a2a_proxy_helpers.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/workspace-server/internal/handlers/a2a_proxy_helpers.go b/workspace-server/internal/handlers/a2a_proxy_helpers.go index 98c51bb7d..11916e6b1 100644 --- a/workspace-server/internal/handlers/a2a_proxy_helpers.go +++ b/workspace-server/internal/handlers/a2a_proxy_helpers.go @@ -407,15 +407,6 @@ func validateCallerToken(ctx context.Context, c *gin.Context, callerID string) e // matching (the wsauth errors are typed for the invalid case). var errInvalidCallerToken = errors.New("missing caller auth token") -// canvasUserMessage holds the extracted user message extracted from an -// A2A canvas request body for broadcasting to other sessions. -type canvasUserMessage struct { - Message string `json:"message,omitempty"` - Parts []map[string]interface{} `json:"parts,omitempty"` - MessageID string `json:"messageId,omitempty"` - Attachments []map[string]interface{} `json:"attachments,omitempty"` -} - // extractCanvasUserMessage parses an A2A JSON-RPC request body and extracts // the user-authored text and attachments from a canvas-initiated message/send. // Returns nil when the body is not a canvas user message (empty, malformed, -- 2.52.0