fix(core): check RowsAffected errors in admin_schedules_health, org_import, llm_billing_mode #2107

Merged
devops-engineer merged 3 commits from fix/rows-affected-core into main 2026-06-01 23:28:30 +00:00
6 changed files with 34 additions and 7 deletions
@@ -243,7 +243,12 @@ func (h *AdminSchedulesHealthHandler) ReapOrphans(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "re-point failed"})
return
}
repointedN, _ := repointed.RowsAffected()
repointedN, err := repointed.RowsAffected()
if err != nil {
log.Printf("ReapOrphans: repointed rows affected: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "re-point failed"})
return
}
// 2. Disable any remaining schedules still bound to a removed/missing
// workspace (no live successor, or template schedules on a dead row).
@@ -261,7 +266,12 @@ func (h *AdminSchedulesHealthHandler) ReapOrphans(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": "disable failed"})
return
}
disabledN, _ := disabled.RowsAffected()
disabledN, err := disabled.RowsAffected()
if err != nil {
log.Printf("ReapOrphans: disabled rows affected: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "disable failed"})
return
}
log.Printf("ReapOrphans: re-pointed %d, disabled %d orphaned schedule(s)", repointedN, disabledN)
c.JSON(http.StatusOK, gin.H{"repointed": repointedN, "disabled": disabledN})
@@ -252,6 +252,9 @@ func scanAuditRows(rows *sql.Rows) ([]auditEventRow, error) {
}
result = append(result, ev)
}
if err := rows.Err(); err != nil {
return nil, err
}
return result, nil
}
@@ -377,6 +377,9 @@ func readWorkspaceDeriveInputs(ctx context.Context, workspaceID string) (runtime
availableAuthEnv = append(availableAuthEnv, k)
}
}
if err := rows.Err(); err != nil {
log.Printf("llm_billing_mode: read secrets rows error for %s: %v (deriving with partial model/auth-env)", workspaceID, err)
}
return runtime, model, availableAuthEnv
}
@@ -453,7 +456,10 @@ func SetWorkspaceLLMBillingMode(ctx context.Context, workspaceID, mode string) e
if err != nil {
return fmt.Errorf("clear workspace llm_billing_mode for %s: %w", workspaceID, err)
}
n, _ := res.RowsAffected()
n, err := res.RowsAffected()
if err != nil {
return fmt.Errorf("clear workspace llm_billing_mode rows affected %s: %w", workspaceID, err)
}
if n == 0 {
return sql.ErrNoRows
}
@@ -470,7 +476,10 @@ func SetWorkspaceLLMBillingMode(ctx context.Context, workspaceID, mode string) e
if err != nil {
return fmt.Errorf("set workspace llm_billing_mode for %s: %w", workspaceID, err)
}
n, _ := res.RowsAffected()
n, err := res.RowsAffected()
if err != nil {
return fmt.Errorf("set workspace llm_billing_mode rows affected %s: %w", workspaceID, err)
}
if n == 0 {
return sql.ErrNoRows
}
@@ -750,7 +750,12 @@ func (h *OrgHandler) migrateRuntimeSchedulesFromRemovedPredecessor(ctx context.C
log.Printf("Org import: schedule migration %s -> %s (%q) failed: %v", predID, newID, name, err)
return
}
if n, _ := res.RowsAffected(); n > 0 {
n, err := res.RowsAffected()
if err != nil {
log.Printf("Org import: schedule migration rows affected %s -> %s: %v", predID, newID, err)
return
}
if n > 0 {
log.Printf("Org import: migrated %d runtime schedule(s) from removed predecessor %s to new workspace %s (%q)", n, predID, newID, name)
}
}
@@ -141,7 +141,7 @@ func requireCallerOwnsOrg(c *gin.Context) (string, error) {
orgID, err := orgtoken.OrgIDByTokenID(c.Request.Context(), db.DB, tokID)
if err != nil {
// DB error — deny by default rather than risk cross-org access.
return "", fmt.Errorf("allowlist: requireCallerOwnsOrg: %v", err)
return "", fmt.Errorf("allowlist: requireCallerOwnsOrg: %w", err)
}
return orgID, nil
}
+1 -1
View File
@@ -79,7 +79,7 @@ func isSafeURL(rawURL string) error {
}
addrs, err := net.LookupHost(host)
if err != nil {
return fmt.Errorf("DNS resolution blocked for hostname: %s (%v)", host, err)
return fmt.Errorf("DNS resolution blocked for hostname: %s (%w)", host, err)
}
if len(addrs) == 0 {
return fmt.Errorf("DNS returned no addresses for: %s", host)