Anuken/Mindustry · error · IOException
Invalid Steam ID structure: {}
Error message
Invalid Steam ID structure: {} What it means
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.
Source
Thrown at desktop/src/mindustry/desktop/steam/SNet.java:177
}
@Override
public void connectClient(String ip, int port, Runnable success) throws IOException{
if(ip.startsWith("steam:")){
String lobbyname = ip.substring("steam:".length());
try{
SteamID lobby = SteamID.createFromNativeHandle(Long.parseLong(lobbyname));
joinCallback = success;
smat.joinLobby(lobby);
}catch(NumberFormatException e){
throw new IOException("Invalid Steam ID: " + lobbyname);
}
}else if (ip.startsWith("steamserver:")){
String server = ip.substring("steamserver:".length());
try{
SteamID serverID = SteamID.createFromNativeHandle(Long.parseLong(server));
if(!serverID.isValid()) throw new IOException("Invalid Steam ID structure: " + server);
Core.app.post(() -> {
currentLobby = null;
currentServer = serverID;
joinCallback = success;
//begin the handshake; success/handleClientReceived/setClientConnected fire once onConnectionStatusChanged reports Connected
clientConnection = snet.connectP2P(serverID, 0);
Core.app.post(() -> { // TODO: This gets hidden and I can't figure out how to not do so.
ui.loadfrag.show("@connecting");
ui.loadfrag.setButton(() -> {
ui.loadfrag.hide();
netClient.disconnectQuietly();
});
});
Log.info("Initiated direct Steam P2P connection to server: @", currentServer.getAccountID());View on GitHub (pinned to f695ad7e60)
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.
Example fix
// before
SteamID serverID = SteamID.createFromNativeHandle(Long.parseLong(server));
if(!serverID.isValid()) throw new IOException("Invalid Steam ID structure: " + server);
// after
SteamID serverID = SteamID.createFromNativeHandle(Long.parseLong(server));
if(!serverID.isValid() || serverID.getAccountType() != ACCOUNT_TYPE.GameServer){
throw new IOException("Not a valid gameserver SteamID: " + server + " (type=" + serverID.getAccountType() + ")");
} Defensive patterns
Strategy: validation
Validate before calling
// Run before connectClient when ip starts with "steamserver:"
String raw = ip.substring("steamserver:".length()).trim();
if(!raw.matches("\\d+")) throw new IllegalArgumentException("Not numeric: " + raw);
SteamID id = SteamID.createFromNativeHandle(Long.parseLong(raw));
if(!id.isValid()) throw new IllegalArgumentException("SteamID structurally invalid: " + raw); Type guard
static boolean isValidGameServerSteamID(String ip){
if(ip == null || !ip.startsWith("steamserver:")) return false;
String raw = ip.substring("steamserver:".length()).trim();
if(!raw.matches("\\d+")) return false;
SteamID id = SteamID.createFromNativeHandle(Long.parseLong(raw));
return id.isValid();
} Try / catch
try{
net.connectClient(ip, port, success);
}catch(IOException e){
if(e.getMessage() != null && e.getMessage().startsWith("Invalid Steam ID structure")){
ui.showErrorMessage("@invalidsteam.server");
}else throw e;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Failed to parse server Steam ID: {}
- Invalid Steam ID: {}
- Player cannot configure a tile.
- Player cannot control a building.
- Player cannot control a unit.
AI-assisted analysis of Anuken/Mindustry@f695ad7e60 (2026-08-14).
Data as JSON: /api/errors/d8222764d680b902.
Report an issue: GitHub.