googleapis/mcp-toolbox · error
could not unmarshal operation: %w
Error message
could not unmarshal operation: %w
What it means
After successfully marshaling a DONE operation, the library unmarshals the bytes into map[string]any so generateCloudSQLConnectionMessage can extract connection details. If json.Unmarshal fails on bytes that were just marshaled from a sqladmin.Operation, this error is thrown. This should be unreachable with valid operation data and signals a corrupted payload or a marshaling/serialization mismatch.
Source
Thrown at internal/sources/cloudsqladmin/cloud_sql_admin.go:370
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) {
backupRun := &sqladmin.BackupRun{}
if location != "" {
backupRun.Location = location
}
if backupDescription != "" {View on GitHub (pinned to 8cc6e09de2)
Solutions
- Upgrade google.golang.org/api to the latest version
- Log opBytes content on failure to inspect what was produced and why it cannot unmarshal
- Bypass the map conversion: pass opBytes or a typed struct to the connection-message generator instead
- Verify no proxy/middleware is transforming the API response payload
Example fix
// before
var data map[string]any
if err := json.Unmarshal(opBytes, &data); err != nil {
return nil, fmt.Errorf("could not unmarshal operation: %w", err)
}
// after
var data map[string]any
if err := json.Unmarshal(opBytes, &data); err != nil {
return nil, fmt.Errorf("could not unmarshal operation %s: %w (raw: %s)", operation, err, string(opBytes))
} Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the marshaled operation bytes decode into a map before downstream use
func operationDecodable(opBytes []byte) error {
var probe map[string]any
if err := json.Unmarshal(opBytes, &probe); err != nil {
return fmt.Errorf("operation bytes not decodable: %w", err)
}
return nil
} Type guard
func decodeOperation(opBytes []byte) (map[string]any, bool) {
var data map[string]any
if err := json.Unmarshal(opBytes, &data); err != nil {
return nil, false
}
return data, true
} Try / catch
result, err := src.GetWaitForOperations(ctx, service, project, opName, tpl, delay)
if err != nil && strings.Contains(err.Error(), "could not unmarshal operation") {
// Graceful fallback: return the raw operation JSON via REST
resp, rerr := service.Operations.Get(project, opName).Do()
if rerr == nil {
raw, _ := json.Marshal(resp)
fmt.Println(string(raw))
}
return
} Prevention
- Update google.golang.org/api; a MarshalJSON/Unmarshal mismatch is a library bug, not user error
- Avoid proxies/interceptors that rewrite JSON payloads between the API and the client
- Add raw-JSON fallback logging so operation results are never lost to a decode failure
When it happens
Trigger: op.MarshalJSON() succeeded but produced bytes that json.Unmarshal into map[string]any rejects — e.g. malformed JSON from a custom/broken MarshalJSON implementation or a struct containing a function/invalid field rendered incorrectly.
Common situations: Essentially only seen with a broken or mismatched google.golang.org/api version, patched client code, or intercepting proxies that corrupt the operation JSON before it reaches local marshaling.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- operation finished with error but could not marshal error ob
- operation finished with error: %s
- could not marshal 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/9ee379cd8cb74db2.
Report an issue: GitHub.