knadh/listmonk · error
could not not decode type %T -> %T
Error message
could not not decode type %T -> %T
What it means
StringIntMap implements sql.Scanner; Scan expects nil or []byte (JSONB from Postgres). If the driver delivers any other Go type, json.Unmarshal can't be attempted and this (typo'd) error is returned describing the source and target types.
Source
Thrown at models/common.go:133
// StringIntMap is used to define DB Scan()s.
type StringIntMap map[string]int
// Value returns the JSON marshalled SubscriberAttribs.
func (s JSON) Value() (driver.Value, error) {
return json.Marshal(s)
}
// Scan unmarshals JSONB from the DB.
func (s JSON) Scan(b any) error {
if b == nil {
s = make(JSON)
return nil
}
if data, ok := b.([]byte); ok {
return json.Unmarshal(data, &s)
}
return fmt.Errorf("could not not decode type %T -> %T", b, s)
}
// Scan unmarshals JSONB from the DB.
func (s StringIntMap) Scan(src any) error {
if src == nil {
s = make(StringIntMap)
return nil
}
if data, ok := src.([]byte); ok {
return json.Unmarshal(data, &s)
}
return fmt.Errorf("could not not decode type %T -> %T", src, s)
}
// Scan implements the sql.Scanner interface.
func (h *Headers) Scan(src any) error {
var b []byteView on GitHub (pinned to 670c01717d)
Solutions
- Add a string case: if data, ok := b.(string); ok { return json.Unmarshal([]byte(data), &s) }
- Ensure the query doesn't cast the JSONB column to text; select it as-is so the driver returns []byte
- Pass []byte(...) when calling Scan directly in tests/code
Example fix
// before
if data, ok := b.([]byte); ok {
return json.Unmarshal(data, &s)
}
// after
switch data := b.(type) {
case []byte:
return json.Unmarshal(data, &s)
case string:
return json.Unmarshal([]byte(data), &s)
} Defensive patterns
Strategy: type-guard
Validate before calling
switch v := value.(type) {
case nil, []byte:
// OK to pass to Scan
case string:
value = []byte(v)
default:
return fmt.Errorf("cannot scan %T into StringIntMap", value)
} Type guard
func isScannableJSONB(v any) bool {
switch v.(type) {
case nil, []byte, string:
return true
}
return false
} Try / catch
if err := m.Scan(dbValue); err != nil {
if strings.Contains(err.Error(), "could not not decode") {
// coerce dbValue to []byte (if string) and retry once
}
} Prevention
- Select JSONB columns without ::text casts
- Pin a single Postgres driver so JSONB consistently arrives as []byte
- Extend Scan with a string case for defensive parsing
When it happens
Trigger: Database/driver returns a value that is neither nil nor []byte — e.g. a string instead of []byte — when scanning a JSONB column into StringIntMap.
Common situations: Using a driver or scan helper that decodes JSONB into string instead of []byte; hand-written queries casting the column (e.g. ::text); unit tests passing string values to Scan.
Related errors
- subscribers.invalidJSON
- error parsing lang file: %s: %v
- error reading validation data: %v
- error unmarshalling azure notification array: %v
- error unmarshalling azure event: %v
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/3a61fc5db173b8d2.
Report an issue: GitHub.