{"record":{"id":"451b14cf8ce2e9ed","repo":"ent/ent","slug":"schema-interceptors-panics-v","errorCode":null,"errorMessage":"schema.Interceptors panics: %v","messagePattern":"schema\\.Interceptors panics: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"entc/load/schema.go","lineNumber":488,"sourceCode":"\treturn schema.Mixin(), nil\n}\n\n// safeHooks wraps the schema.Hooks method with recover to ensure no panics in marshaling.\nfunc safeHooks(schema interface{ Hooks() []ent.Hook }) (hooks []ent.Hook, err error) {\n\tdefer func() {\n\t\tif v := recover(); v != nil {\n\t\t\terr = fmt.Errorf(\"schema.Hooks panics: %v\", v)\n\t\t\thooks = nil\n\t\t}\n\t}()\n\treturn schema.Hooks(), nil\n}\n\n// safeInterceptors wraps the schema.Interceptors method with recover to ensure no panics in marshaling.\nfunc safeInterceptors(schema interface{ Interceptors() []ent.Interceptor }) (inters []ent.Interceptor, err error) {\n\tdefer func() {\n\t\tif v := recover(); v != nil {\n\t\t\terr = fmt.Errorf(\"schema.Interceptors panics: %v\", v)\n\t\t\tinters = nil\n\t\t}\n\t}()\n\treturn schema.Interceptors(), nil\n}\n\n// safePolicy wraps the schema.Policy method with recover to ensure no panics in marshaling.\nfunc safePolicy(schema interface{ Policy() ent.Policy }) (policy ent.Policy, err error) {\n\tdefer func() {\n\t\tif v := recover(); v != nil {\n\t\t\terr = fmt.Errorf(\"schema.Policy panics: %v\", v)\n\t\t\tpolicy = nil\n\t\t}\n\t}()\n\treturn schema.Policy(), nil\n}\n\nfunc indirect(t reflect.Type) reflect.Type {","sourceCodeStart":470,"sourceCodeEnd":506,"githubUrl":"https://github.com/ent/ent/blob/69d5d4deb19599f129166634e09d33addcf3f2cc/entc/load/schema.go#L470-L506","documentation":"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.","triggerScenarios":"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.","commonSituations":"Interceptors defined in other packages with uninitialized dependencies; generation-time vs runtime configuration mismatches; copy-paste errors after renaming types.","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"],"exampleFix":"// before\nfunc (MySchema) Interceptors() []ent.Interceptor {\n    return []ent.Interceptor{tracingIntercept.(*softDeleteInterceptor)} // panics if wrong type\n}\n// after\nfunc (MySchema) Interceptors() []ent.Interceptor {\n    si, ok := tracingIntercept.(*softDeleteInterceptor)\n    if !ok {\n        return nil\n    }\n    return []ent.Interceptor{si}\n}","handlingStrategy":"validation","validationCode":"func validateInterceptors(s interface{ Interceptors() []ent.Interceptor }) (err error) {\n    defer func() {\n        if v := recover(); v != nil {\n            err = fmt.Errorf(\"Interceptors() panicked: %v\", v)\n        }\n    }()\n    s.Interceptors()\n    return nil\n}","typeGuard":"inter, ok := candidate.(ent.Interceptor); if !ok { return nil }","tryCatchPattern":null,"preventionTips":["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"],"tags":["go","ent","codegen","panic","interceptors"],"backgroundTag":"schema-panic-during-codegen","analyzedSha":"69d5d4deb19599f129166634e09d33addcf3f2cc","analyzedAt":"2026-09-03T16:51:39.799Z","contentChangedAt":"2026-09-03T16:51:39.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}