ory/hydra · error
cannot scan %#v into StringSliceJSONFormat
Error message
cannot scan %#v into StringSliceJSONFormat
What it means
StringSliceJSONFormat implements sql.Scanner for a []string stored as JSON. Its Scan accepts nil, string, and []byte only; any other driver value (int, float64, time.Time, bool, etc.) is rejected with this error. It indicates the source column is not a text/JSON column carrying a JSON array document.
Source
Thrown at oryx/sqlxx/types.go:61
}
// StringSliceJSONFormat represents []string{} which is encoded to/from JSON for SQL storage.
// swagger:type array
type StringSliceJSONFormat []string
// Scan implements the Scanner interface.
func (m *StringSliceJSONFormat) Scan(value interface{}) error {
var val string
switch v := value.(type) {
case nil:
*m = StringSliceJSONFormat{}
return nil
case string:
val = v
case []byte:
val = string(v)
default:
return errors.Errorf("cannot scan %#v into StringSliceJSONFormat", value)
}
if len(val) == 0 {
val = "[]"
}
if parsed := gjson.Parse(val); parsed.Type == gjson.Null {
val = "[]"
} else if !parsed.IsArray() {
return errors.Errorf("expected JSON value to be an array but got type: %s", parsed.Type.String())
}
return errors.WithStack(json.Unmarshal([]byte(val), &m))
}
// Value implements the driver Valuer interface.
func (m StringSliceJSONFormat) Value() (driver.Value, error) {
if len(m) == 0 {
return "[]", nilView on GitHub (pinned to 4174065ffb)
Solutions
- Change the column to TEXT or JSON/JSONB storing a JSON array (e.g. '["a","b"]') via a migration.
- Cast in SQL: SELECT col::text FROM ... so the driver delivers a string/[]byte.
- Scan into the driver's native Go type first, marshal it to a JSON array, then assign to StringSliceJSONFormat.
- If the column truly holds scalars, change the model field type — StringSliceJSONFormat is only for arrays.
Example fix
// before
rows.Scan(&tags) // tags is sqlxx.StringSliceJSONFormat; column is INT -> error
// after
rows.Scan("SELECT tags::text")
// or migrate column: ALTER TABLE items ALTER COLUMN tags TYPE jsonb USING ...; Defensive patterns
Strategy: type-guard
Validate before calling
var dataType string err := db.QueryRow(`SELECT data_type FROM information_schema.columns WHERE table_name=$1 AND column_name=$2`, "items", "tags").Scan(&dataType) // acceptable: "text", "character varying", "json", "jsonb"
Type guard
func scannableIntoStringSlice(v any) bool {
switch v.(type) {
case nil, string, []byte:
return true
default:
return false
}
} Try / catch
var tags sqlxx.StringSliceJSONFormat
if err := rows.Scan(&tags); err != nil {
if strings.Contains(err.Error(), "cannot scan") {
// column returned a non-text driver type; fetch as text or fix column
return fmt.Errorf("tags column is not text/json: %w", err)
}
return err
} Prevention
- Store string slices in TEXT or JSONB columns containing JSON arrays.
- Cast to ::text in raw queries feeding StringSliceJSONFormat fields.
- Keep model field types in sync with column types when refactoring schemas.
- Test Scan behavior against each supported driver in CI.
When it happens
Trigger: Scanning a column of numeric, boolean, timestamp, or native-JSON-object-driver type into a *StringSliceJSONFormat field; raw queries returning non-text expressions into that field; a driver that decodes JSONB into non-string types.
Common situations: Model field changed from a string slice to a scalar but the Scan type was left in place; column switched from TEXT/JSONB to BIGINT; migrating data where an old column held CSV/integer ids now being read into the JSON-based type.
Related errors
- unable to scan type %T as JSON into %T
- expected JSON value to be an array but got type: %s
- cannot scan %T into region.Region
- cookiex: payload must be a flat JSON object with string valu
- unable to decode JSON payload into %T: %w
AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03).
Data as JSON: /api/errors/a59ae638f677c83a.
Report an issue: GitHub.