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

  1. Confirm the identifier is a gameserver SteamID64, not a lobby handle or bare account ID.
  2. Call SteamID.isValid() yourself before connectClient and surface a precise error to the user.
  3. Re-fetch the server ID from the authoritative source (lobby metadata, server browser) rather than user input.
  4. 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

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


AI-assisted analysis of Anuken/Mindustry@f695ad7e60 (2026-08-14). Data as JSON: /api/errors/d8222764d680b902. Report an issue: GitHub.