googleapis/mcp-toolbox · error
failed to marshal operation to JSON: %w
Error message
failed to marshal operation to JSON: %w
What it means
GetOperation fetches a Dataplex long-running operation and serializes it with protojson to return JSON to the caller. If protojson cannot marshal the returned *longrunningpb.Operation (nil pointer or invalid proto state), the error is wrapped as 'failed to marshal operation to JSON'. This is an internal serialization failure, not an API error.
Source
Thrown at internal/sources/dataplex/dataplex.go:922
return s.DataScanClient.GetDataScan(ctx, req)
}
func (s *Source) GetOperation(ctx context.Context, opName string) (map[string]any, error) {
if !operationNameRegex.MatchString(opName) {
return nil, fmt.Errorf("invalid operation name format: %q (expected projects/*/locations/*/operations/*)", opName)
}
req := &longrunningpb.GetOperationRequest{
Name: opName,
}
op, err := s.DataScanClient.LROClient.GetOperation(ctx, req)
if err != nil {
return nil, err
}
bytes, err := protojson.Marshal(op)
if err != nil {
return nil, fmt.Errorf("failed to marshal operation to JSON: %w", err)
}
var opData map[string]any
if err := json.Unmarshal(bytes, &opData); err != nil {
return nil, fmt.Errorf("failed to unmarshal operation JSON to map: %w", err)
}
return opData, nil
}
func (s *Source) GetJobStatus(ctx context.Context, location, scanID, jobID string) (*dataplexpb.DataScanJob, error) {
// If jobID is provided, fetch that specific job directly!
if jobID != "" {
name := fmt.Sprintf("projects/%s/locations/%s/dataScans/%s/jobs/%s", s.ProjectID(), location, scanID, jobID)
req := &dataplexpb.GetDataScanJobRequest{
Name: name,
}
return s.DataScanClient.GetDataScanJob(ctx, req)View on GitHub (pinned to 8cc6e09de2)
Solutions
- Check that the operation name passed to GetOperation exists and the client returned a non-nil operation
- Verify the google.golang.org/genproto dataplex/longrunning proto versions are consistent (go mod tidy / go get -u)
- If using a mock client, ensure the stub returns a valid *longrunningpb.Operation
- Log the underlying wrapped error (%w) to see the exact protojson failure
Example fix
// before
op, err := src.GetOperation(ctx, "")
// after
if opName == "" {
return errors.New("operation name is required")
}
op, err := src.GetOperation(ctx, opName) Defensive patterns
Strategy: try-catch
Validate before calling
if op == nil || op.GetName() == "" { return errors.New("no operation returned") } Type guard
op, ok := resp.(*longrunningpb.Operation); if !ok || op == nil { ... } Try / catch
op, err := src.GetOperation(ctx, name)
if err != nil {
var uerr interface{ Unwrap() error }
if errors.As(err, &uerr) { log.Printf("underlying: %v", uerr) }
return fmt.Errorf("get operation failed: %w", err)
} Prevention
- Never call GetOperation with an empty operation name
- Keep proto/genproto dependencies aligned across modules
- Validate mocks return fully-formed Operation messages
When it happens
Trigger: Calling GetOperation when the Dataplex client returns an operation value that protojson cannot encode — typically a nil operation pointer or a corrupt/invalid proto message.
Common situations: Operation not found paths returning nil without error from a stub; passing an operation from a mismatched proto package version; mocking the DataScanClient with an invalid message.
Related errors
- operation finished with error but could not marshal error ob
- failed to initialize dataplex client: %w
- failed to create Dataplex client for project %q: %w
- failed to get dataplex client: %w
- failed to get project details for project %q: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/0ebde7cd433c32aa.
Report an issue: GitHub.