{"record":{"id":"d8222764d680b902","repo":"Anuken/Mindustry","slug":"invalid-steam-id-structure","errorCode":null,"errorMessage":"Invalid Steam ID structure: {}","messagePattern":"Invalid Steam ID structure: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"desktop/src/mindustry/desktop/steam/SNet.java","lineNumber":177,"sourceCode":"    }\n\n    @Override\n    public void connectClient(String ip, int port, Runnable success) throws IOException{\n\n        if(ip.startsWith(\"steam:\")){\n            String lobbyname = ip.substring(\"steam:\".length());\n            try{\n                SteamID lobby = SteamID.createFromNativeHandle(Long.parseLong(lobbyname));\n                joinCallback = success;\n                smat.joinLobby(lobby);\n            }catch(NumberFormatException e){\n                throw new IOException(\"Invalid Steam ID: \" + lobbyname);\n            }\n        }else if (ip.startsWith(\"steamserver:\")){\n            String server = ip.substring(\"steamserver:\".length());\n            try{\n                SteamID serverID = SteamID.createFromNativeHandle(Long.parseLong(server));\n                if(!serverID.isValid()) throw new IOException(\"Invalid Steam ID structure: \" + server);\n\n                Core.app.post(() -> {\n                    currentLobby = null;\n                    currentServer = serverID;\n                    joinCallback = success;\n\n                    //begin the handshake; success/handleClientReceived/setClientConnected fire once onConnectionStatusChanged reports Connected\n                    clientConnection = snet.connectP2P(serverID, 0);\n\n                    Core.app.post(() -> {  // TODO: This gets hidden and I can't figure out how to not do so.\n                        ui.loadfrag.show(\"@connecting\");\n                        ui.loadfrag.setButton(() -> {\n                            ui.loadfrag.hide();\n                            netClient.disconnectQuietly();\n                        });\n                    });\n\n                    Log.info(\"Initiated direct Steam P2P connection to server: @\", currentServer.getAccountID());","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/Anuken/Mindustry/blob/f695ad7e60323ebced984fa26d0bcf0bc54296b4/desktop/src/mindustry/desktop/steam/SNet.java#L159-L195","documentation":"Thrown in the 'steamserver:' branch after SteamID.createFromNativeHandle succeeds (the value was numeric) but serverID.isValid() returns false. Steam's SteamID encodes an account type, universe, and account ID in its bits; isValid() checks that structure. A number that parses as a long yet does not form a well-formed gameserver SteamID triggers this.","triggerScenarios":"Calling connectClient(\"steamserver:<digits>\", ...) where <digits> is numeric but is not a structurally valid gameserver SteamID (wrong account type/universe, all-zero account ID, or a lobby ID used in place of a server ID).","commonSituations":"Confusing a lobby SteamID with a gameserver SteamID; passing an account ID instead of a full SteamID64; using a stale/historic ID whose type bits no longer validate; transposing digits so the result parses but is malformed.","solutions":["Confirm the identifier is a gameserver SteamID64, not a lobby handle or bare account ID.","Call SteamID.isValid() yourself before connectClient and surface a precise error to the user.","Re-fetch the server ID from the authoritative source (lobby metadata, server browser) rather than user input.","Distinguish the failure path from the parse-failure path so users know it is a structure problem, not a typo."],"exampleFix":"// before\nSteamID serverID = SteamID.createFromNativeHandle(Long.parseLong(server));\nif(!serverID.isValid()) throw new IOException(\"Invalid Steam ID structure: \" + server);\n\n// after\nSteamID serverID = SteamID.createFromNativeHandle(Long.parseLong(server));\nif(!serverID.isValid() || serverID.getAccountType() != ACCOUNT_TYPE.GameServer){\n    throw new IOException(\"Not a valid gameserver SteamID: \" + server + \" (type=\" + serverID.getAccountType() + \")\");\n}","handlingStrategy":"validation","validationCode":"// Run before connectClient when ip starts with \"steamserver:\"\nString raw = ip.substring(\"steamserver:\".length()).trim();\nif(!raw.matches(\"\\\\d+\")) throw new IllegalArgumentException(\"Not numeric: \" + raw);\nSteamID id = SteamID.createFromNativeHandle(Long.parseLong(raw));\nif(!id.isValid()) throw new IllegalArgumentException(\"SteamID structurally invalid: \" + raw);","typeGuard":"static boolean isValidGameServerSteamID(String ip){\n    if(ip == null || !ip.startsWith(\"steamserver:\")) return false;\n    String raw = ip.substring(\"steamserver:\".length()).trim();\n    if(!raw.matches(\"\\\\d+\")) return false;\n    SteamID id = SteamID.createFromNativeHandle(Long.parseLong(raw));\n    return id.isValid();\n}","tryCatchPattern":"try{\n    net.connectClient(ip, port, success);\n}catch(IOException e){\n    if(e.getMessage() != null && e.getMessage().startsWith(\"Invalid Steam ID structure\")){\n        ui.showErrorMessage(\"@invalidsteam.server\");\n    }else throw e;\n}","preventionTips":["Source server IDs from authoritative metadata (lobby data, server browser), never raw user typing.","Pre-validate with SteamID.isValid() and account-type checks before attempting a connection.","Keep lobby IDs and gameserver IDs in separate, type-distinct fields to prevent misuse."],"tags":["networking","steam","validation","server"],"backgroundTag":null,"analyzedSha":"f695ad7e60323ebced984fa26d0bcf0bc54296b4","analyzedAt":"2026-08-14T04:31:16.262Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}