XTLS/Xray-core · error · errors.Error
failed to close logger
Error message
failed to close logger
What it means
RestartLogger closes the existing log.Instance before starting it again; if logger.Close() returns an error it is wrapped with this message. Close flushes and releases file log writers, so failures usually come from the underlying file (already closed, permission removed, disk gone).
Source
Thrown at app/log/command/command.go:24
"github.com/xtls/xray-core/app/log"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/core"
grpc "google.golang.org/grpc"
)
type LoggerServer struct {
V *core.Instance
}
// RestartLogger implements LoggerService.
func (s *LoggerServer) RestartLogger(ctx context.Context, request *RestartLoggerRequest) (*RestartLoggerResponse, error) {
logger := s.V.GetFeature((*log.Instance)(nil))
if logger == nil {
return nil, errors.New("unable to get logger instance")
}
if err := logger.Close(); err != nil {
return nil, errors.New("failed to close logger").Base(err)
}
if err := logger.Start(); err != nil {
return nil, errors.New("failed to start logger").Base(err)
}
return &RestartLoggerResponse{}, nil
}
func (s *LoggerServer) mustEmbedUnimplementedLoggerServiceServer() {}
type service struct {
v *core.Instance
}
func (s *service) Register(server *grpc.Server) {
ls := &LoggerServer{
V: s.v,
}
RegisterLoggerServiceServer(server, ls)View on GitHub (pinned to 7d214f8b09)
Solutions
- Check the chained Base error for the exact file operation that failed
- Restore write permission / recreate the log directory and retry the restart
- Configure logrotate with copytruncate or signal Xray instead of deleting the file out from under it
Defensive patterns
Strategy: try-catch
Validate before calling
// Before restarting, confirm the log file is still writable:
if access := logger.AccessLogPath(); access != "" {
if f, err := os.OpenFile(access, os.O_APPEND|os.O_WRONLY, 0o644); err != nil {
// fix path/permissions before calling RestartLogger
} else { f.Close() }
} Try / catch
resp, err := loggerClient.RestartLogger(ctx, req)
if err != nil && strings.Contains(err.Error(), "failed to close logger") {
// inspect grpc details for the base file error; restore the log file and retry once
} Prevention
- Use logrotate copytruncate or HUP instead of deleting live log files
- Ensure the log directory persists across container restarts
- Avoid concurrent RestartLogger calls
When it happens
Trigger: RestartLogger invoked when the log file was deleted, its directory unmounted, permissions changed, or the writer already closed by a concurrent restart.
Common situations: logrotate moving the file away while the API restart fires; read-only filesystems in containers; two concurrent RestartLogger calls racing on the same instance.
Related errors
- failed to start logger
- unable to get logger instance
- failed to initialize access logger
- failed to initialize error logger
- unsupported router implementation
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/925f4d210bd79497.
Report an issue: GitHub.