googleapis/mcp-toolbox · error
could not marshal operation: %w
Error message
could not marshal operation: %w
What it means
After a successful DONE operation, the library calls op.MarshalJSON() to serialize the full operation object for the response. If that built-in marshaling fails, this error is thrown. In practice this is near-impossible with stock sqladmin.Operation types unless the API client library is mismatched or the object holds unusual ForceSendFields/NullFields state.
Source
Thrown at internal/sources/cloudsqladmin/cloud_sql_admin.go:365
}
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
}
return string(opBytes), nil
}
logger.DebugContext(ctx, fmt.Sprintf("operation not complete, retrying in %v", delay))
}
return nil, nil
}
func (s *Source) InsertBackupRun(ctx context.Context, project, instance, location, backupDescription, accessToken string) (any, error) {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Upgrade the google.golang.org/api dependency to the latest version
- Fall back to json.Marshal(op) in the handler to capture and inspect the failure
- Log the operation name and retrieve it via gcloud sql operations describe instead of in-process marshaling
- Pin consistent versions of google.golang.org/api across the build to avoid generated-type mismatches
Example fix
// before
opBytes, err = op.MarshalJSON()
if err != nil {
return nil, fmt.Errorf("could not marshal operation: %w", err)
}
// after
opBytes, err = op.MarshalJSON()
if err != nil {
logger.WarnContext(ctx, fmt.Sprintf("op.MarshalJSON failed (%v), falling back to json.Marshal", err))
if opBytes, err = json.Marshal(op); err != nil {
return nil, fmt.Errorf("could not marshal operation %s: %w", op.Name, err)
}
} Defensive patterns
Strategy: fallback
Validate before calling
// Pre-check that the operation object serializes cleanly right after fetch
func operationSerializable(op *sqladmin.Operation) error {
if _, err := op.MarshalJSON(); err != nil {
return fmt.Errorf("operation %s not serializable: %w", op.Name, err)
}
return nil
} Type guard
func canMarshalOperation(op *sqladmin.Operation) ([]byte, bool) {
b, err := op.MarshalJSON()
if err != nil {
if b2, err2 := json.Marshal(op); err2 == nil {
return b2, true
}
return nil, false
}
return b, true
} Try / catch
result, err := src.GetWaitForOperations(ctx, service, project, opName, tpl, delay)
if err != nil && strings.Contains(err.Error(), "could not marshal operation") {
// fallback: fetch and describe via CLI or raw HTTP
out, cmdErr := exec.Command("gcloud", "sql", "operations", "describe", opName, "--project", project, "--format=json").Output()
if cmdErr == nil {
fmt.Println(string(out))
}
return
} Prevention
- Pin and regularly update google.golang.org/api to avoid generated-type serialization bugs
- Avoid custom wrapping or field mutation of sqladmin.Operation before serialization
- Have an out-of-band fallback (gcloud / REST API) to retrieve operation results
When it happens
Trigger: service.Operations.Get returned a DONE operation with no op.Error, but op.MarshalJSON() returned a non-nil error during result serialization in GetWaitForOperations.
Common situations: Version incompatibility between the generated sqladmin API types and the serialization helpers, corrupted client state, or unusual operation payloads from newer API versions not understood by an older google.golang.org/api version.
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
- operation finished with error but could not marshal error ob
- 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/d1c610993f5e5a10.
Report an issue: GitHub.