{"record":{"id":"06fe6c25eade480e","repo":"googleapis/mcp-toolbox","slug":"failed-to-unmarshal-cluster-json-w","errorCode":null,"errorMessage":"failed to unmarshal cluster JSON: %w","messagePattern":"failed to unmarshal cluster JSON: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/dataproc/dataproc.go","lineNumber":244,"sourceCode":"\treq := &dataprocpb.GetClusterRequest{\n\t\tProjectId:   s.Project,\n\t\tRegion:      s.Region,\n\t\tClusterName: clusterName,\n\t}\n\n\tclusterPb, err := client.GetCluster(ctx, req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get cluster: %w\", err)\n\t}\n\n\tjsonBytes, err := protojson.Marshal(clusterPb)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal cluster to JSON: %w\", err)\n\t}\n\n\tvar result map[string]any\n\tif err := json.Unmarshal(jsonBytes, &result); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal cluster JSON: %w\", err)\n\t}\n\n\tconsoleUrl := ClusterConsoleURLFromProto(clusterPb, s.Region)\n\tlogsUrl := ClusterLogsURLFromProto(clusterPb, s.Region)\n\n\twrappedResult := map[string]any{\n\t\t\"consoleUrl\": consoleUrl,\n\t\t\"logsUrl\":    logsUrl,\n\t\t\"cluster\":    result,\n\t}\n\n\treturn wrappedResult, nil\n}\n\n// ListJobsResponse is the response from the list jobs API.\ntype ListJobsResponse struct {\n\tJobs          []Job  `json:\"jobs\"`\n\tNextPageToken string `json:\"nextPageToken\"`","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/dataproc/dataproc.go#L226-L262","documentation":"Thrown by GetCluster when json.Unmarshal fails to decode the marshaled cluster JSON into a map[string]any. Since the input came from protojson.Marshal, this is nearly always a sign of empty/invalid intermediate data rather than malformed cluster content.","triggerScenarios":"json.Unmarshal(jsonBytes, &result) receiving empty or non-JSON bytes — only realistically possible if the protojson.Marshal step produced invalid output or jsonBytes was mutated.","commonSituations":"Version-skew bugs in serialization; custom builds with modified code; effectively unreachable in normal operation given the preceding marshal succeeded.","solutions":["Log/inspect jsonBytes when this fires to confirm what was produced by protojson.Marshal.","Update google.golang.org/protobuf and the dataproc module to latest versions.","Replace the two-step protojson->JSON->map conversion with a single protojson.Marshal into a struct if customizing the code."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"if len(jsonBytes) == 0 || !json.Valid(jsonBytes) {\n    return errors.New(\"invalid JSON produced from cluster proto\")\n}","tryCatchPattern":"cluster, err := src.GetCluster(ctx, name)\nif err != nil && strings.Contains(err.Error(), \"unmarshal cluster JSON\") {\n    // internal serialization issue: capture jsonBytes, update deps, report upstream\n    return err\n}","preventionTips":["Keep protobuf and dataproc module versions current and compatible.","Don't mutate intermediate JSON between marshal and unmarshal.","Prefer a single protojson decode step when customizing the code."],"tags":["dataproc","serialization","json"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}