geektutu/7days-golang · error
panic(p)
Error message
panic(p)
What it means
In Transaction (day6-transaction), the deferred recover handler re-throws any panic (panic(p)) after rolling back the transaction. This is not an error the library invents — it preserves an original panic that occurred inside the transaction callback (e.g. an 'invalid sql type' schema panic or a nil-map panic) while guaranteeing Rollback ran first.
Source
Thrown at gee-orm/day6-transaction/geeorm.go:66
// NewSession creates a new session for next operations
func (engine *Engine) NewSession() *session.Session {
return session.New(engine.db, engine.dialect)
}
// TxFunc will be called between tx.Begin() and tx.Commit()
// https://stackoverflow.com/questions/16184238/database-sql-tx-detecting-commit-or-rollback
type TxFunc func(*session.Session) (interface{}, error)
// Transaction executes sql wrapped in a transaction, then automatically commit if no error occurs
func (engine *Engine) Transaction(f TxFunc) (result interface{}, err error) {
s := engine.NewSession()
if err := s.Begin(); err != nil {
return nil, err
}
defer func() {
if p := recover(); p != nil {
_ = s.Rollback()
panic(p) // re-throw panic after Rollback
} else if err != nil {
_ = s.Rollback() // err is non-nil; don't change it
} else {
err = s.Commit() // err is nil; if Commit returns error update err
}
}()
return f(s)
}
View on GitHub (pinned to cf36443821)
Solutions
- Look at the original panic value/stack trace chained below this re-throw — the root cause is inside the transaction callback or the schema
- Fix the underlying panic source (e.g. unsupported field type in the model)
- If you need to convert panics to errors, wrap the s.Transaction call in your own recover at the caller level
Example fix
// before
_ = db.Transaction(func(s *geeorm.Session) error {
return s.Raw(...).Find(&users) // may panic on bad schema
})
// after
func safeTx(db *geeorm.Engine) (err error) {
defer func() { if p := recover(); p != nil { err = fmt.Errorf("tx panic: %v", p) } }()
return db.Transaction(func(s *geeorm.Session) error {
return s.Raw(...).Find(&users)
})
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the model is schema-valid before entering the transaction
if err := checkSchemaTypes(&Order{}); err != nil {
return err
}
return db.Transaction(func(s *geeorm.Session) error { ... }) Try / catch
func runTx(db *geeorm.Engine) (err error) {
defer func() {
if p := recover(); p != nil {
err = fmt.Errorf("transaction panicked (rolled back): %v", p)
}
}()
return db.Transaction(func(s *geeorm.Session) error {
// transaction body
return nil
})
} Prevention
- Treat the re-thrown panic as the original panic — read its stack, the bug is in your callback or schema
- Validate model schemas before opening transactions
- Keep transaction callbacks free of code that can panic (bounds checks, nil checks)
When it happens
Trigger: Any panic raised inside the transaction's function body or its deferred chain: e.g. DataTypeOf panicking on an unsupported field type, a nil pointer in the callback, or Commit-side panics — all surface as this re-thrown panic after rollback.
Common situations: A schema bug (like error 107's invalid sql type) occurring mid-transaction; user callback code dividing by zero or indexing nil; bugs in hook code executed inside the transaction.
Related errors
- panic(p)
- invalid sql type %s (%s)
- invalid sql type %s (%s)
- invalid sql type %s (%s)
- invalid sql type %s (%s)
AI-assisted analysis of geektutu/7days-golang@cf36443821 (2026-09-03).
Data as JSON: /api/errors/0ef0169a3ebff1c6.
Report an issue: GitHub.