{"record":{"id":"91c4dc1877d5d06a","repo":"googleapis/mcp-toolbox","slug":"unable-to-unmarshal-json-w","errorCode":null,"errorMessage":"unable to unmarshal JSON: %w","messagePattern":"unable to unmarshal JSON: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/spanner/spanner.go","lineNumber":157,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to parse row: %w\", err)\n\t\t}\n\n\t\trowMap := orderedmap.Row{}\n\t\tcols := row.ColumnNames()\n\t\tfor i, c := range cols {\n\t\t\tif c == \"object_details\" { // for list graphs or list tables\n\t\t\t\tval := row.ColumnValue(i)\n\t\t\t\tif val == nil { // ColumnValue returns the Cloud Spanner Value of column i, or nil for invalid column.\n\t\t\t\t\trowMap.Add(c, nil)\n\t\t\t\t} else {\n\t\t\t\t\tjsonString, ok := val.AsInterface().(string)\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"column 'object_details' is not a string, but %T\", val.AsInterface())\n\t\t\t\t\t}\n\t\t\t\t\tvar details map[string]any\n\t\t\t\t\tif err := json.Unmarshal([]byte(jsonString), &details); err != nil {\n\t\t\t\t\t\treturn nil, fmt.Errorf(\"unable to unmarshal JSON: %w\", err)\n\t\t\t\t\t}\n\t\t\t\t\trowMap.Add(c, details)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trowMap.Add(c, row.ColumnValue(i))\n\t\t\t}\n\t\t}\n\t\tout = append(out, rowMap)\n\t}\n\treturn out, nil\n}\n\nfunc (s *Source) RunSQL(ctx context.Context, readOnly bool, statement string, params map[string]any) (any, error) {\n\tvar results []any\n\tvar err error\n\tvar opErr error\n\tstmt := spanner.Statement{\n\t\tSQL: statement,","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/spanner/spanner.go#L139-L175","documentation":"In processRows (internal/sources/spanner/spanner.go:157), after successfully reading a string column value, the code runs json.Unmarshal on it to produce a map[string]any for 'object_details'. If the string is not valid JSON (malformed syntax, empty string, truncated payload), the unmarshal fails and this wrapped error is returned. The underlying json.UnmarshalSyntaxError/TypeError is included via %w.","triggerScenarios":"A Spanner STRING column that the code expects to contain a JSON object contains invalid JSON: malformed braces, an empty string, plain text, or a JSON array instead of an object.","commonSituations":"Application code wrote non-JSON text into a JSON-designated column; truncated writes; column contains 'null' scalar or a JSON array where the code expects map[string]any; data corruption from a bad ETL job.","solutions":["Validate the stored data: SELECT the column and run it through a JSON linter to find the malformed rows","Fix the producer writing the column so it serializes valid JSON objects","If arrays/other shapes are expected, change the unmarshal target from map[string]any to json.RawMessage or a matching type","Clean up or repair corrupted rows with an UPDATE or re-run the ETL job"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func isValidJSONObject(s string) bool {\n\tvar m map[string]any\n\treturn json.Unmarshal([]byte(s), &m) == nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate JSON at write time in the producing application","Add a CHECK(json_valid(object_details)) constraint in Spanner-adjacent stores or ETL validation","Round-trip test ETL output against json.Unmarshal"],"tags":["spanner","json","unmarshal"],"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"}