From f88f60b1766a63f4eef8e41dbb53d54fb9c399b4 Mon Sep 17 00:00:00 2001 From: Calabe Davis Date: Fri, 12 Jun 2026 07:34:57 -0700 Subject: [PATCH] Fix nil panic when kicking a link-dead session at login users.GetByUserId returns nil when the target session has already been removed from the active user map (e.g. link-dead cleanup between the kick prompt and the answer). Answering "y" to the kick prompt then dereferenced a nil UserRecord and crashed the server. Skip the kick when there is no live session and proceed with the normal login flow. Co-Authored-By: Claude Fable 5 --- internal/inputhandlers/login.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/internal/inputhandlers/login.go b/internal/inputhandlers/login.go index 19d896a40..a23de4830 100644 --- a/internal/inputhandlers/login.go +++ b/internal/inputhandlers/login.go @@ -34,14 +34,21 @@ func FinalizeLoginOrCreate(results map[string]string, sharedState map[string]any userid := users.FindUserId(results["username"]) user := users.GetByUserId(userid) - existingConnectionId := user.ConnectionId() + // The session may have disappeared since the kick prompt (e.g. link-dead + // cleanup), in which case there's nothing to kick. This also covers + // FindUserId returning 0, since GetByUserId(0) returns nil. + if user != nil { - // Send a goodbye message to the currently connected user - tplTxt, _ := templates.Process("goodbye", nil) - connections.SendTo([]byte(templates.AnsiParse(tplTxt)), existingConnectionId) + existingConnectionId := user.ConnectionId() - users.SetLinkDeadUser(userid) - connections.Kick(existingConnectionId, fmt.Sprintf(`Duplicate login (ip: %s)`, connDetails.RemoteAddr())) + // Send a goodbye message to the currently connected user + tplTxt, _ := templates.Process("goodbye", nil) + connections.SendTo([]byte(templates.AnsiParse(tplTxt)), existingConnectionId) + + users.SetLinkDeadUser(userid) + connections.Kick(existingConnectionId, fmt.Sprintf(`Duplicate login (ip: %s)`, connDetails.RemoteAddr())) + + } }