jmoiron/sqlx · error

Incompatible type for JSONText

Error message

Incompatible type for JSONText

What it means

JSONText.Scan implements sql.Scanner and accepts string, []byte, and nil (SQL NULL maps to empty JSON). Any other driver type cannot be treated as JSON text, so Scan returns this error. The message is capitalized intentionally to preserve backwards compatibility.

Source

Thrown at types/types.go:106

}

// Scan stores the src in *j.  No validation is done.
func (j *JSONText) Scan(src interface{}) error {
	var source []byte
	switch t := src.(type) {
	case string:
		source = []byte(t)
	case []byte:
		if len(t) == 0 {
			source = emptyJSON
		} else {
			source = t
		}
	case nil:
		*j = emptyJSON
	default:
		//lint:ignore ST1005 changing this could break consumers of this package
		return errors.New("Incompatible type for JSONText")
	}
	*j = append((*j)[0:0], source...)
	return nil
}

// Unmarshal unmarshal's the json in j to v, as in json.Unmarshal.
func (j *JSONText) Unmarshal(v interface{}) error {
	if len(*j) == 0 {
		*j = emptyJSON
	}
	return json.Unmarshal([]byte(*j), v)
}

// String supports pretty printing for JSONText types.
func (j JSONText) String() string {
	return string(j)
}

View on GitHub (pinned to 41dac167fd)

Solutions

  1. Verify the column actually stores JSON as text and the driver returns []byte/string.
  2. Scan into []byte first and assign via j.Scan(raw) or append manually.
  3. Use the correct sqlx type for the column's real type (Int64Text-like handling or plain types).
  4. Upgrade/downgrade the driver or configure it to return strings for text columns.

Example fix

// before
var j types.JSONText
row.Scan(&j) // src is time.Time
// after
var raw []byte
row.Scan(&raw)
j.Scan(raw)
Defensive patterns

Strategy: type-guard

Validate before calling

func jsonTextScannable(src interface{}) bool {
	switch src.(type) {
	case []byte, string, nil:
		return true
	default:
		return false
	}
}

Type guard

func assertJSONSource(v interface{}) ([]byte, bool) {
	switch t := v.(type) {
	case []byte:
		return t, true
	case string:
		return []byte(t), true
	}
	return nil, false
}

Try / catch

var j types.JSONText
if err := row.Scan(&j); err != nil {
	if err.Error() == "Incompatible type for JSONText" {
		// log reflect.TypeOf(src) from a plain interface{} scan
	}
	return err
}

Prevention

When it happens

Trigger: Scanning a column whose driver value is neither string, []byte, nor nil into a JSONText field — e.g. int64/float64 from a numeric column, time.Time from a timestamp column, or bool.

Common situations: JSONText used on an integer/timestamp column by mistake; a driver returning different types for TEXT/BLOB (some return string, others []byte, some custom types); ORM/driver version changes altering returned types.

Related errors


AI-assisted analysis of jmoiron/sqlx@41dac167fd (2026-09-03). Data as JSON: /api/errors/d915cf8537bf0519. Report an issue: GitHub.