Anuken/Mindustry · warning · ValidateException

Player cannot control a building.

Error message

Player cannot control a building.

What it means

Thrown server-side as ValidateException when buildingControlSelect fails authorization: possession is not allowed by rules (state.rules.possessionAllowed is false AND player.bestCore() != build) OR netServer.admins.allowAction(buildSelect) denies it. Validates that a player may take direct control of a building (e.g. core units / turret possession).

Source

Thrown at core/src/mindustry/input/InputHandler.java:747

        Events.fire(new ConfigEvent(build, player, value));
    }

    //only useful for servers or local mods, and is not replicated across clients
    //uses unreliable packets due to high frequency
    @Remote(targets = Loc.both, called = Loc.both, unreliable = true)
    public static void tileTap(@Nullable Player player, Tile tile){
        if(tile == null) return;

        Events.fire(new TapEvent(player, tile));
    }

    @Remote(targets = Loc.both, called = Loc.server)
    public static void buildingControlSelect(Player player, Building build){
        if(player == null || build == null || player.dead()) return;

        //make sure player is allowed to control the building
        if(net.server() && (!state.rules.possessionAllowed && player.bestCore() != build  || !netServer.admins.allowAction(player, ActionType.buildSelect, action -> action.tile = build.tile))){
            throw new ValidateException(player, "Player cannot control a building.");
        }

        if(player.team() == build.team && build.canControlSelect(player.unit())){
            var before = player.unit();

            Call.unitBuildingControlSelect(player.unit(), build);

            if(!before.dead && before.spawnedByCore && !before.isPlayer()){
                Call.unitDespawn(before);
            }
        }
    }

    @Remote(called = Loc.server)
    public static void unitBuildingControlSelect(Unit unit, Building build){
        if(unit == null || unit.dead()) return;

        //client skips checks to prevent ghost units

View on GitHub (pinned to f695ad7e60)

Solutions

  1. On the server, handle ValidateException gracefully (it is an expected rejection).
  2. Clients should check state.rules.possessionAllowed and team match before requesting control.
  3. Review permission/admin configuration if legitimate control is blocked.

Example fix

// before
Call.buildingControlSelect(player, build);

// after
if(state.rules.possessionAllowed && player.team() == build.team()){
    Call.buildingControlSelect(player, build);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// client checks rules and team before requesting building control
if(!state.rules.possessionAllowed && player.bestCore() != build){
    return;
}
if(player.team() != build.team()){ return; }

Try / catch

try{ Call.buildingControlSelect(player, build); }catch(mindustry.net.ValidateException e){ Log.debug("rejected build control from @", e.player); }

Prevention

When it happens

Trigger: Client sends buildingControlSelect for a build when possession is disallowed by rules, or the admin layer denies the buildSelect action. Server-only throw (the @Remote called=Loc.server).

Common situations: Game mode/server disables possession (possessionAllowed=false) but a client still attempts it; permission plugin denies build control; client attempts to control an enemy-team building.

Related errors


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