googleapis/mcp-toolbox · error · ClientServerError

pre-check operation failed with error: %s

Error message

pre-check operation failed with error: %s

What it means

The Cloud SQL Admin pre-check long-running operation (LRO) completed with status DONE but carried a non-empty error list, meaning Google's pre-check for the major version upgrade rejected the operation. The tool surfaces the first error's message (and code, if present) as a 500-class client server error.

Source

Thrown at internal/tools/cloudsqlpg/cloudsqlpgupgradeprecheck/cloudsqlpgupgradeprecheck.go:195

		return nil, util.ProcessGcpError(err)
	}

	const pollTimeout = 20 * time.Second
	cutoffTime := time.Now().Add(pollTimeout)

	for time.Now().Before(cutoffTime) {
		currentOp, err := service.Operations.Get(project, op.Name).Context(ctx).Do()
		if err != nil {
			return nil, util.ProcessGcpError(err)
		}

		if currentOp.Status == "DONE" {
			if currentOp.Error != nil && len(currentOp.Error.Errors) > 0 {
				errMsg := fmt.Sprintf("pre-check operation LRO failed: %s", currentOp.Error.Errors[0].Message)
				if currentOp.Error.Errors[0].Code != "" {
					errMsg = fmt.Sprintf("%s (Code: %s)", errMsg, currentOp.Error.Errors[0].Code)
				}
				return nil, util.NewClientServerError(errMsg, http.StatusInternalServerError, fmt.Errorf("pre-check operation failed with error: %s", errMsg))
			}

			var preCheckItems []*sqladmin.PreCheckResponse
			if currentOp.PreCheckMajorVersionUpgradeContext != nil {
				preCheckItems = currentOp.PreCheckMajorVersionUpgradeContext.PreCheckResponse
			}
			// convertResults handles nil or empty preCheckItems
			return PreCheckAPIResponse{Items: convertResults(preCheckItems)}, nil
		}

		select {
		case <-ctx.Done():
			return nil, util.NewClientServerError("timed out waiting for operation", http.StatusRequestTimeout, ctx.Err())
		case <-time.After(5 * time.Second):
		}
	}
	return op, nil
}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Read the embedded errMsg (message plus Code) — it comes from the Cloud SQL API and names the blocking condition
  2. Fix the flagged condition (e.g. upgrade through intermediate versions, adjust instance settings, grant sqladmin roles)
  3. Re-run the pre-check after correcting; if transient (capacity/quota), retry later
  4. Check the operation ID in Cloud Audit Logs / Cloud Console for the full error detail
Defensive patterns

Strategy: retry

Validate before calling

// Pre-validate instance eligibility via Cloud SQL Admin API before invoking:
op, err := sqladminService.Instances.Get(project, instance).Do()
if err != nil || op.Settings.DataDiskSizeGb < required { return fmt.Errorf("instance not eligible for pre-check") }

Type guard

func opFailed(op *sqladmin.Operation) (string, bool) {
    if op.Status == "DONE" && op.Error != nil && len(op.Error.Errors) > 0 {
        return op.Error.Errors[0].Message, true
    }
    return "", false
}

Try / catch

result, err := tool.Invoke(ctx, src, params, token)
if err != nil {
    // errMsg contains the Cloud SQL error message and code, e.g. "(Code: ...)
    if isRetryableCode(err) { backoffAndRetry(ctx, tool, args) }
    return fmt.Errorf("upgrade pre-check rejected: %w", err)
}

Prevention

When it happens

Trigger: Invoking cloudsqlpg-upgrade-precheck where the LRO returned DONE with currentOp.Error.Errors non-empty — e.g. unsupported version path, insufficient disk/ML capacity checks failing, instance state not eligible for upgrade, or IAM permission problems on the Cloud SQL Admin API.

Common situations: Pre-checking an upgrade from an unsupported minor version; instance with read replicas or HA settings blocking the path; quota/permission denials surfacing as LRO errors; regional capacity unavailable for the target version.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/325ef811caf46029. Report an issue: GitHub.