googleapis/mcp-toolbox · error
operation finished with error: %s
Error message
operation finished with error: %s
What it means
This error is returned by GetOperations when a polled AlloyDB long-running operation has completed unsuccessfully: op.Done is true and op.Error is non-nil. The Google Rpc.Status object (HTTP status code and error message from the failed operation) is JSON-marshaled and embedded in this message, so the full failure reason is in the error text. It represents the authoritative failure of a create/delete/patch operation, not a client-side problem.
Source
Thrown at internal/sources/alloydbadmin/alloydbadmin.go:351
service, err := s.getService(ctx, accessToken)
if err != nil {
return nil, err
}
name := fmt.Sprintf("projects/%s/locations/%s/operations/%s", project, location, operation)
op, err := service.Projects.Locations.Operations.Get(name).Do()
if err != nil {
logger.DebugContext(ctx, fmt.Sprintf("error getting operation: %s, retrying in %v\n", err, delay))
} else {
if op.Done {
if op.Error != nil {
var errorBytes []byte
errorBytes, err = json.Marshal(op.Error)
if err != nil {
return nil, fmt.Errorf("operation finished with error but could not marshal error object: %w", err)
}
return nil, fmt.Errorf("operation finished with error: %s", string(errorBytes))
}
var opBytes []byte
opBytes, err = op.MarshalJSON()
if err != nil {
return nil, fmt.Errorf("could not marshal operation: %w", err)
}
if op.Response != nil {
var responseData map[string]any
if err := json.Unmarshal(op.Response, &responseData); err == nil && responseData != nil {
if msg, ok := generateAlloyDBConnectionMessage(responseData, connectionMessageTemplate); ok {
return msg, nil
}
}
}
var result anyView on GitHub (pinned to 8cc6e09de2)
Solutions
- Parse the JSON payload in the message (fields code and message) to read the API's failure reason
- If the code indicates quota (e.g., 8/RESOURCE_EXHAUSTED or 429), check AlloyDB quotas in the Cloud Console and request an increase
- If permissions-related, verify the caller's IAM roles include roles/alloydb.admin before re-running the operation
- Fix the underlying configuration (machine type, network, region) and resubmit the create/update request
- Check Cloud Logging for the operation's detailed server-side logs for root cause
Example fix
// before
if op.Error != nil {
errorBytes, _ := json.Marshal(op.Error)
return nil, fmt.Errorf("operation finished with error: %s", string(errorBytes))
}
// after
if op.Error != nil {
var rpcStatus struct {
Code int `json:"code"`
Message string `json:"message"`
}
if b, err := json.Marshal(op.Error); err == nil && json.Unmarshal(b, &rpcStatus) == nil {
return nil, fmt.Errorf("operation failed (gRPC code %d): %s", rpcStatus.Code, rpcStatus.Message)
}
errorBytes, _ := json.Marshal(op.Error)
return nil, fmt.Errorf("operation finished with error: %s", string(errorBytes))
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: pre-flight checks before starting/polling an operation
if err := checkQuotaAndBilling(project); err != nil {
return fmt.Errorf("preflight failed: %w", err)
}
// ensure config (machine type, region, network) is valid before submitting Type guard
func ParseOperationFailure(err error) (grpcCode int, message string, ok bool) {
const prefix = "operation finished with error: "
msg := err.Error()
i := strings.Index(msg, prefix)
if i < 0 {
return 0, "", false
}
var st struct {
Code int `json:"code"`
Message string `json:"message"`
}
if json.Unmarshal([]byte(msg[i+len(prefix):]), &st) != nil {
return 0, "", false
}
return st.Code, st.Message, true
} Try / catch
_, err := s.GetOperations(ctx, project, location, opName, tmpl, pollDelay, accessToken)
if err != nil {
if code, msg, ok := ParseOperationFailure(err); ok {
switch code {
case 8: // RESOURCE_EXHAUSTED
return fmt.Errorf("quota exceeded: %s — request quota increase", msg)
case 7: // PERMISSION_DENIED
return fmt.Errorf("IAM permission missing: %s", msg)
default:
return fmt.Errorf("operation failed: %s", msg)
}
}
return err
} Prevention
- Check AlloyDB quotas and billing status before launching instance operations
- Validate instance configuration against API docs before submitting
- Parse the JSON in the error message to react to specific gRPC codes
- Watch Cloud Logging for server-side root causes of failed operations
When it happens
Trigger: Polling an operation via Projects.Locations.Operations.Get whose target action failed server-side — e.g., instance creation rejected due to quota exhaustion, invalid configuration, permission denial, or resource conflicts — and the API returned Done=true with an Error status.
Common situations: Exceeded AlloyDB quota or regional capacity, invalid instance settings (machine type, network), permission revoked between request start and completion, project billing issues, and conflicts like a duplicate resource created concurrently.
Related errors
- operation finished with error but could not marshal error ob
- error creating AlloyDB instance: %w
- error creating AlloyDB user: %w
- error getting AlloyDB cluster: %w
- error getting AlloyDB instance: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/06d58395788c0ef6.
Report an issue: GitHub.