{"record":{"id":"70a4218e2c9089ac","repo":"googleapis/mcp-toolbox","slug":"column-object-details-is-not-a-string-but-t","errorCode":null,"errorMessage":"column 'object_details' is not a string, but %T","messagePattern":"column 'object_details' is not a string, but %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/spanner/spanner.go","lineNumber":153,"sourceCode":"\t\trow, err := iter.Next()\n\t\tif err == iterator.Done {\n\t\t\tbreak\n\t\t}\n\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","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/spanner/spanner.go#L135-L171","documentation":"In processRows (internal/sources/spanner/spanner.go:153), the Spanner source expects a column's value to convert to a Go string via val.AsInterface().(string) — this is used to parse JSON 'object_details' columns into maps. When the Spanner value's underlying Go type is not a string (e.g. []byte, int64, float64, bool), the type assertion fails and this error is returned. It indicates the query returned a non-JSON/non-string value in a column the code path treats as a JSON string payload.","triggerScenarios":"Calling RunSQL/InvokeSearchCatalog through the Spanner source where a result column's value from row.ColumnValue(i).AsInterface() is not a string — e.g. the search/catalog query returns numeric or []byte columns instead of JSON text.","commonSituations":"Spanner returning JSON columns as []byte with certain drivers/settings; a schema change altered a column from STRING to NUMERIC/BOOL; using a custom SQL query that selects non-string columns into a code path expecting 'object_details' JSON.","solutions":["Inspect the column types in your query result and ensure the JSON payload column is a Spanner STRING","Cast the column in SQL: SELECT CAST(object_details AS STRING) AS object_details ...","If the value arrives as []byte, convert with string(val) before unmarshalling in processRows","Check for recent schema migrations that changed the column's type away from STRING"],"exampleFix":"// before\nSELECT object_details FROM objects;\n// after\nSELECT CAST(object_details AS STRING) AS object_details FROM objects;","handlingStrategy":"type-guard","validationCode":"// verify the column is STRING before running the tool\n// in Spanner: SELECT column_name, spanner_type FROM information_schema.columns WHERE table_name = 'objects';","typeGuard":"func asJSONString(v any) (string, bool) {\n\ts, ok := v.(string)\n\tif !ok {\n\t\tif b, ok2 := v.([]byte); ok2 {\n\t\t\treturn string(b), true\n\t\t}\n\t\treturn \"\", false\n\t}\n\treturn s, true\n}","tryCatchPattern":null,"preventionTips":["Keep JSON payload columns as Spanner STRING type","CAST in SQL when column type may vary","Assert the schema in CI with information_schema checks"],"tags":["spanner","type-assertion","json-column"],"backgroundTag":"column-type-mismatch","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"}