{"record":{"id":"7060da732dcebaf9","repo":"ory/hydra","slug":"cannot-scan-t-into-jsonrawmessage","errorCode":null,"errorMessage":"cannot scan %T into JSONRawMessage","messagePattern":"cannot scan %T into JSONRawMessage","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/sqlxx/types.go","lineNumber":396,"sourceCode":"\t}\n\n\treturn string(m), nil\n}\n\n// JSONRawMessage represents a json.RawMessage that works well with JSON, SQL, and Swagger.\ntype JSONRawMessage json.RawMessage\n\n// Scan implements the Scanner interface.\nfunc (m *JSONRawMessage) Scan(value interface{}) error {\n\tswitch v := value.(type) {\n\tcase []byte:\n\t\t*m = slices.Clone(v)\n\tcase string:\n\t\t*m = JSONRawMessage(v)\n\tcase nil:\n\t\t*m = JSONRawMessage(\"null\")\n\tdefault:\n\t\treturn errors.Errorf(\"cannot scan %T into JSONRawMessage\", value)\n\t}\n\treturn nil\n}\n\n// Value implements the driver Valuer interface.\nfunc (m JSONRawMessage) Value() (driver.Value, error) {\n\tif len(m) == 0 {\n\t\treturn \"null\", nil\n\t}\n\treturn string(m), nil\n}\n\n// MarshalJSON returns m as the JSON encoding of m.\nfunc (m JSONRawMessage) MarshalJSON() ([]byte, error) {\n\tif len(m) == 0 {\n\t\treturn []byte(\"null\"), nil\n\t}\n\treturn m, nil","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/sqlxx/types.go#L378-L414","documentation":"JSONRawMessage.Scan supports copying from []byte, string, and nil database values. Any other Go type returned by the driver (e.g. float64 from some drivers, time.Time, or a nested value) has no conversion defined, so Scan returns this error naming the unsupported type %T. It is a type-contract failure between the driver and this Valuer/Scanner type.","triggerScenarios":"Scanning a column into JSONRawMessage when the database driver returns a type other than []byte, string, or nil — e.g. some drivers return numeric/text columns as int64, float64, or time.Time.","commonSituations":"Using a driver that decodes JSON columns differently (Postgres drivers usually give []byte, but SQLite or MySQL drivers may return string variants or other types); mapping a non-JSON column into a JSONRawMessage field.","solutions":["Cast the column in SQL to text/json: SELECT col::text AS col so the driver returns a string or []byte.","Prefer the pq/postgres driver or configure the driver to return strings for JSON columns.","Change the field type to match what the driver actually returns (e.g. string, []byte) and convert manually."],"exampleFix":"// before\nrows.QueryRow(\"SELECT metadata FROM events\").Scan(&raw) // raw is sqlxx.JSONRawMessage, driver returns float64\n// after\nrows.QueryRow(\"SELECT metadata::text AS metadata FROM events\").Scan(&raw)","handlingStrategy":"type-guard","validationCode":"switch v := dbValue.(type) {\ncase []byte, string, nil:\n    // safe to Scan into JSONRawMessage\ndefault:\n    // convert first: fmt.Sprintf(\"%v\", v) or marshal v\n}","typeGuard":"func scannableIntoJSONRawMessage(v any) bool {\n    switch v.(type) {\n    case []byte, string, nil:\n        return true\n    default:\n        return false\n    }\n}","tryCatchPattern":"// value is *errors.Error from oryx/pkg/errors\nvar raw sqlxx.JSONRawMessage\nif err := row.Scan(&raw); err != nil {\n    if strings.Contains(err.Error(), \"cannot scan\") {\n        var s string\n        if e2 := row.Scan(&s); e2 == nil {\n            raw = sqlxx.JSONRawMessage(s)\n        }\n    }\n}","preventionTips":["Cast JSON columns to text in SQL (col::text) so drivers return strings/bytes.","Prefer drivers known to return []byte/string for JSON columns (lib/pq, pgx default).","Do not map non-JSON columns (numeric, timestamp) into JSONRawMessage fields."],"tags":["json","database-scan","type-mismatch","sql-driver"],"backgroundTag":"json-scan-type-mismatch","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}