ent/ent · error
schema.Interceptors panics: %v
Error message
schema.Interceptors panics: %v
What it means
safeInterceptors wraps a schema's Interceptors() method with a recover handler during entc schema loading. If Interceptors() panics, the panic becomes this error so marshaling reports it instead of crashing. The defect is in the user's Interceptors() implementation.
Source
Thrown at entc/load/schema.go:488
return schema.Mixin(), nil
}
// safeHooks wraps the schema.Hooks method with recover to ensure no panics in marshaling.
func safeHooks(schema interface{ Hooks() []ent.Hook }) (hooks []ent.Hook, err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("schema.Hooks panics: %v", v)
hooks = nil
}
}()
return schema.Hooks(), nil
}
// safeInterceptors wraps the schema.Interceptors method with recover to ensure no panics in marshaling.
func safeInterceptors(schema interface{ Interceptors() []ent.Interceptor }) (inters []ent.Interceptor, err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("schema.Interceptors panics: %v", v)
inters = nil
}
}()
return schema.Interceptors(), nil
}
// safePolicy wraps the schema.Policy method with recover to ensure no panics in marshaling.
func safePolicy(schema interface{ Policy() ent.Policy }) (policy ent.Policy, err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("schema.Policy panics: %v", v)
policy = nil
}
}()
return schema.Policy(), nil
}
func indirect(t reflect.Type) reflect.Type {View on GitHub (pinned to 69d5d4deb1)
Solutions
- Call Interceptors() in a test to reproduce and fix the panic at its source
- Read the %v payload to identify the panicking value/operation
- Nil-check interceptor values before returning them
- Keep Interceptors() side-effect free and dependent only on static schema data
Example fix
// before
func (MySchema) Interceptors() []ent.Interceptor {
return []ent.Interceptor{tracingIntercept.(*softDeleteInterceptor)} // panics if wrong type
}
// after
func (MySchema) Interceptors() []ent.Interceptor {
si, ok := tracingIntercept.(*softDeleteInterceptor)
if !ok {
return nil
}
return []ent.Interceptor{si}
} Defensive patterns
Strategy: validation
Validate before calling
func validateInterceptors(s interface{ Interceptors() []ent.Interceptor }) (err error) {
defer func() {
if v := recover(); v != nil {
err = fmt.Errorf("Interceptors() panicked: %v", v)
}
}()
s.Interceptors()
return nil
} Type guard
inter, ok := candidate.(ent.Interceptor); if !ok { return nil } Prevention
- Use comma-ok type assertions instead of direct casts when building interceptors
- Nil-check interceptor variables
- Keep Interceptors() free of external dependencies
- Cover Interceptors() with unit tests
When it happens
Trigger: entc schema loading where Interceptors() panics — e.g. nil interceptor variable dereferenced during construction, out-of-range slice access, or wrong type assertion when building the interceptor list.
Common situations: Interceptors defined in other packages with uninitialized dependencies; generation-time vs runtime configuration mismatches; copy-paste errors after renaming types.
Related errors
- mixin %q: %w
- %T.Fields panics: %v
- schema.Edges panics: %v
- schema.Indexes panics: %v
- schema.Mixin panics: %v
AI-assisted analysis of ent/ent@69d5d4deb1 (2026-09-03).
Data as JSON: /api/errors/451b14cf8ce2e9ed.
Report an issue: GitHub.