googleapis/mcp-toolbox · error
operation finished with error but could not marshal error ob
Error message
operation finished with error but could not marshal error object: %w
What it means
When a Cloud SQL operation reaches DONE status with a non-nil op.Error, the library attempts to json.Marshal op.Error to include its details in the returned error. If marshaling fails (extremely rare for API-generated OperationErrors, e.g. due to a client/version mismatch producing unmarshalable fields), this wrapper error is thrown instead of the operation's actual error. It indicates the operation failed but its error payload could not be serialized.
Source
Thrown at internal/sources/cloudsqladmin/cloud_sql_admin.go:357
return resp, nil
}
func (s *Source) GetWaitForOperations(ctx context.Context, service *sqladmin.Service, project, operation, connectionMessageTemplate string, delay time.Duration) (any, error) {
logger, err := util.LoggerFromContext(ctx)
if err != nil {
return nil, err
}
op, err := service.Operations.Get(project, operation).Do()
if err != nil {
logger.DebugContext(ctx, fmt.Sprintf("error getting operation: %s, retrying in %v", err, delay))
} else {
if op.Status == "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)
}
var data map[string]any
if err := json.Unmarshal(opBytes, &data); err != nil {
return nil, fmt.Errorf("could not unmarshal operation: %w", err)
}
if msg, ok := generateCloudSQLConnectionMessage(ctx, s, logger, data, connectionMessageTemplate); ok {
return msg, nil
}View on GitHub (pinned to 8cc6e09de2)
Solutions
- Upgrade google.golang.org/api (sqladmin package) to the latest version to fix any marshaling incompatibility
- Inspect op.Error fields directly via debugging/logging instead of relying on marshaling
- Log the operation name and fetch it with gcloud sql operations describe to see the real failure
- Check whether a proxy or modified client is corrupting API responses
Example fix
// before
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)
}
// after
if errorBytes, err = json.Marshal(op.Error); err != nil {
return nil, fmt.Errorf("operation finished with error (status=%s, errors=%v; marshal failed: %w)", op.Status, op.Error, err)
} Defensive patterns
Strategy: type-guard
Validate before calling
// Nothing meaningful can be validated pre-call; optionally sanity-check the client library version
import _ "google.golang.org/api/sqladmin/v1"
func checkClientUsable(op *sqladmin.Operation) error {
if op == nil {
return fmt.Errorf("nil operation")
}
if _, err := json.Marshal(op.Error); err != nil {
return fmt.Errorf("pre-check: op.Error is not marshalable: %w", err)
}
return nil
} Type guard
func operationErrorMarshalable(op *sqladmin.Operation) (string, bool) {
if op == nil || op.Error == nil {
return "", false
}
b, err := json.Marshal(op.Error)
if err != nil {
return fmt.Sprintf("%+v", op.Error), false
}
return string(b), true
} Try / catch
result, err := src.GetWaitForOperations(ctx, service, project, opName, tpl, delay)
if err != nil && strings.Contains(err.Error(), "could not marshal error object") {
// Fall back to raw API inspection
op, _ := service.Operations.Get(project, opName).Do()
if op != nil && op.Error != nil {
for _, e := range op.Error.Errors {
log.Printf("operation error: code=%s message=%s", e.Code, e.Message)
}
}
return
} Prevention
- Keep google.golang.org/api up to date so generated types marshal correctly
- Prefer reading structured fields (op.Error.Errors[].Code/Message) over JSON strings for error reporting
- Add a fallback in error handling that describes the operation via gcloud sql operations describe
When it happens
Trigger: service.Operations.Get returned an operation with Status == "DONE" and op.Error != nil, but json.Marshal(op.Error) returned an error — practically only when the sqladmin library's SqladminEmpty/OperationError types cannot serialize (unsupported types, custom marshaling failure).
Common situations: Almost never seen in practice; would require a corrupted or unexpected op.Error payload from the API, a Go google-cloud-go/sqladmin version incompatibility, or monkey-patched/defective JSON marshaling of the operation error type.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- could not marshal operation: %w
- operation finished with error: %s
- could not unmarshal operation: %w
- error creating instance: %w
- error creating backup: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/2f101e83c802c360.
Report an issue: GitHub.