{"record":{"id":"f42d60a0c406ce66","repo":"XTLS/Xray-core","slug":"unable-to-create-log-handler-for","errorCode":null,"errorMessage":"unable to create log handler for ","messagePattern":"unable to create log handler for ","errorType":"validation","errorClass":"errors.Error","httpStatus":null,"severity":"error","filePath":"app/log/log_creator.go","lineNumber":39,"sourceCode":"func RegisterHandlerCreator(logType LogType, f HandlerCreator) error {\n\tif f == nil {\n\t\treturn errors.New(\"nil HandlerCreator\")\n\t}\n\n\thandlerCreatorMapLock.Lock()\n\tdefer handlerCreatorMapLock.Unlock()\n\n\thandlerCreatorMap[logType] = f\n\treturn nil\n}\n\nfunc createHandler(logType LogType, options HandlerCreatorOptions) (log.Handler, error) {\n\thandlerCreatorMapLock.RLock()\n\tdefer handlerCreatorMapLock.RUnlock()\n\n\tcreator, found := handlerCreatorMap[logType]\n\tif !found {\n\t\treturn nil, errors.New(\"unable to create log handler for \", logType)\n\t}\n\treturn creator(logType, options)\n}\n\nfunc init() {\n\tcommon.Must(RegisterHandlerCreator(LogType_Console, func(lt LogType, options HandlerCreatorOptions) (log.Handler, error) {\n\t\treturn log.NewLogger(log.CreateStdoutLogWriter()), nil\n\t}))\n\n\tcommon.Must(RegisterHandlerCreator(LogType_File, func(lt LogType, options HandlerCreatorOptions) (log.Handler, error) {\n\t\tcreator, err := log.CreateFileLogWriter(options.Path)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn log.NewLogger(creator), nil\n\t}))\n\n\tcommon.Must(RegisterHandlerCreator(LogType_None, func(lt LogType, options HandlerCreatorOptions) (log.Handler, error) {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/log/log_creator.go#L21-L57","documentation":"createHandler looks up a creator function in handlerCreatorMap by LogType; an unknown/unregistered type yields this error with the offending logType embedded. Console and File creators are registered in init(); any other value (including an unparsed string form) has no handler.","triggerScenarios":"RegisterHandlerCreator was never called for the requested LogType — e.g. a config/protobuf supplies a LogType enum value outside LogType_Console/LogType_File, or a custom build skipped the init() registrations.","commonSituations":"Version skew where a newer config format carries a log type this binary does not know; typos when constructing LogType programmatically; stripped builds that exclude the default handler registrations.","solutions":["Use only 'console' or 'file' as the log type in the config","If a custom handler type is needed, call RegisterHandlerCreator for that LogType before creating the log instance","Rebuild/upgrade so the binary and the config's log type vocabulary match"],"exampleFix":"// before (embedding Xray-core)\nlogType := LogType(42) // unregistered\nhandler, err := createHandler(logType, options) // error\n\n// after\nlogType := LogType_File\nhandler, err := createHandler(logType, options)","handlingStrategy":"validation","validationCode":"// Restrict config values to registered handler types before creating the logger:\nswitch logType {\ncase LogType_Console, LogType_File:\n    // ok\ndefault:\n    return fmt.Errorf(\"unsupported log type: %v\", logType)\n}","typeGuard":"func isRegisteredLogType(t LogType) bool {\n    return t == LogType_Console || t == LogType_File\n}","tryCatchPattern":null,"preventionTips":["Only use 'console' and 'file' log types in shipped configs","Register custom handler creators before any logger creation when embedding","Keep config schema and binary version in sync to avoid unknown enum values"],"tags":["logging","config","registry","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}