geektutu/7days-golang · error
invalid sql type %s (%s)
Error message
invalid sql type %s (%s)
What it means
sqlite3.DataTypeOf panics when a schema field's reflect type has no mapping to a SQLite column type. The dialect maps Bool/Int/Float/String/Bytes/Blob and time.Time structs; anything else (slices, maps, pointers, custom structs) is unsupported and triggers this fail-fast panic during schema parsing.
Source
Thrown at gee-orm/day2-reflect-schema/dialect/sqlite3.go:38
case reflect.Bool:
return "bool"
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
return "integer"
case reflect.Int64, reflect.Uint64:
return "bigint"
case reflect.Float32, reflect.Float64:
return "real"
case reflect.String:
return "text"
case reflect.Array, reflect.Slice:
return "blob"
case reflect.Struct:
if _, ok := typ.Interface().(time.Time); ok {
return "datetime"
}
}
panic(fmt.Sprintf("invalid sql type %s (%s)", typ.Type().Name(), typ.Kind()))
}
// TableExistSQL returns SQL that judge whether the table exists in database
func (s *sqlite3) TableExistSQL(tableName string) (string, []interface{}) {
args := []interface{}{tableName}
return "SELECT name FROM sqlite_master WHERE type='table' and name = ?", args
}
View on GitHub (pinned to cf36443821)
Solutions
- Change the unsupported field to a supported type (int, string, float64, []byte, bool, time.Time)
- Serialize complex fields to []byte or string (JSON) and store that
- Add a case to the dialect switch to map the new kind to a SQL type
- Tag or exclude the field from the schema if it should not be persisted
Example fix
// before
type User struct {
Tags map[string]string
}
// after
type User struct {
Tags string // store JSON: json.Marshal(tags) before Save
} Defensive patterns
Strategy: validation
Validate before calling
func checkSchemaTypes(v interface{}) error {
t := reflect.TypeOf(v).Elem()
for i := 0; i < t.NumField(); i++ {
switch t.Field(i).Type.Kind() {
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64, reflect.String, reflect.Slice:
case reflect.Struct:
if t.Field(i).Type != reflect.TypeOf(time.Time{}) {
return fmt.Errorf("field %s: unsupported type %s", t.Field(i).Name, t.Field(i).Type)
}
default:
return fmt.Errorf("field %s: unsupported kind %s", t.Field(i).Name, t.Field(i).Type.Kind())
}
}
return nil
} Type guard
func isSupportedColumnKind(k reflect.Kind) bool {
switch k {
case reflect.Bool, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64, reflect.String, reflect.Slice:
return true
}
return false
} Try / catch
defer func() {
if r := recover(); r != nil {
if s, ok := r.(string); ok && strings.HasPrefix(s, "invalid sql type") {
err = fmt.Errorf("schema field not mappable to sqlite: %s", s)
} else { panic(r) }
}
}() Prevention
- Keep model fields to primitives, []byte, string, and time.Time
- Serialize nested structures as JSON text columns
- Run schema parse in a test at CI time so bad fields surface before runtime
When it happens
Trigger: Defining a Go struct with a field whose type is not one of the supported kinds (e.g. a nested struct other than time.Time, a map, a slice, or a custom named type outside the switch) and calling geeorm.Open on it or New with such a schema.
Common situations: Modeling nested objects (addresses, tags) directly in the struct; embedding a custom value type; renaming a field's type from string to a custom type after a refactor.
Related errors
- invalid sql type %s (%s)
- invalid sql type %s (%s)
- invalid sql type %s (%s)
- invalid sql type %s (%s)
- panic(p)
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/3ad070bf3b636579.
Report an issue: GitHub.