Skip to content

Exceptions

Every error the library raises derives from EmpireError. GGEError, the server's error codes, is in Enums.

exceptions

Every error the library raises; all derive from EmpireError.

Failure modes are kept distinct so callers can react to them individually:

  • EmpireTimeoutError: the server did not answer in time.
  • ConnectionClosedError: the connection dropped while waiting.
  • CommandError: the server answered with a non-zero error code.
  • GameDataNotLoadedError: an API needed the game data and it could not be loaded.
  • AmbiguousLookupError: a game-data lookup matched more than one row.
  • UnknownCastleError: a castle is not one of the logged-in player's castles.
  • AmbiguousCastleError: a castle id or position matches castles in several kingdoms.
  • EventNotRunningError: a call needs an event that is not running.
  • EventHasNoPointsError: a call needs an event that keeps your rank and points.
  • NotInAllianceError: a call needs your alliance and you are in none.
  • ReplyMismatchError: a reply answers another list than the one asked for.
  • UnsendableGoodsError: a market send carries goods the client would not send.
  • PremiumCommanderCostError: a send led by the premium commander may cost rubies.
  • LoginBonusUnavailableError: the login bonus is asked for below the XP the client asks from.

Classes:

Name Description
VersionCheckStatus

The version check (vck) refusals, which are not GGEError codes.

EmpireError

Base class for all EmpireCore exceptions.

NetworkError

Raised when a network operation fails.

ConnectionClosedError

Raised when the connection closes while an operation is in flight.

LoginError

Raised when the login sequence fails.

LoginCooldownError

Raised when the server rejects login due to rate limiting.

AccountBannedError

Raised when the server refuses the login because the account is banned (IS_BANNED, 27).

WrongServerError

Raised when the account belongs to another server (EXISTING_MAPPING_WRONG_SERVER, 368).

ClientVersionError

Raised when the version check (vck) says the client's version is too low or too high.

PacketError

Raised when packet parsing fails.

ReplyMismatchError

Raised when a reply answers another list than the one asked for, e.g. a late hgh reply.

EmpireTimeoutError

Raised when an operation times out.

GameDataNotLoadedError

Raised when an API needs the static game data and it cannot be loaded.

AmbiguousLookupError

Raised when a game-data lookup matches more than one row.

EventNotRunningError

Raised when a call needs an event that is not running: no sei packet named it, or a see ended it.

EventHasNoPointsError

Raised when a call needs an event that keeps your rank and points, and the event keeps none.

NotInAllianceError

Raised when a call needs your own alliance and the player data names none.

UnknownCastleError

Raised when a castle is not in the logged-in player's castle list (gcl).

AmbiguousCastleError

Raised when a castle id or position matches your castles in several kingdoms.

CommandError

Raised when the server responds to a command with a non-zero error code.

AttackInProgressError

The server refused an attack with ATTACK_IN_PROGRESS (234): one of yours is already on its way there.

AttackBelowMinimumError

An attack's waves carry fewer units than the client lets it send.

UnsendableGoodsError

A market send or kingdom transfer carries goods the client's send dialog would not send.

PremiumCommanderCostError

A send led by the premium commander may cost rubies, and the caller did not allow it.

LoginBonusUnavailableError

The login bonus was asked for while your XP is below the client's gate, or not known yet.

ReceiveThreadError

Raised when a call that waits for a reply is made on the receive thread.

MessageUnavailableError

Raised when a message cannot be read: NO_SUCH_MESSAGE or MESSAGEDATA_TOO_OLD (too old to read).

EventStreamOverflowError

Raised by an EventStream given a maxsize once that

VersionCheckStatus

Bases: IntEnum

The version check (vck) refusals, which are not GGEError codes.

Client: VCKCommand.VERSION_TOO_LOW and VERSION_TOO_HIGH (dll line 14473), matched by CastleVCKCommand.executeCommand (bundle line 120444)

Attributes:

Name Type Description
VERSION_TOO_LOW
VERSION_TOO_HIGH

VERSION_TOO_LOW class-attribute instance-attribute

VERSION_TOO_LOW = 1

VERSION_TOO_HIGH class-attribute instance-attribute

VERSION_TOO_HIGH = 2

EmpireError

Bases: Exception

Base class for all EmpireCore exceptions.

NetworkError

Bases: EmpireError

Raised when a network operation fails.

ConnectionClosedError

Bases: NetworkError

Raised when the connection closes while an operation is in flight.

LoginError

LoginError(message: str, code: int | None = None)

Bases: EmpireError

Raised when the login sequence fails.

Attributes:

Name Type Description
code

the server's status code when the server refused the login, else None

error GGEError | None

the matching GGEError member, or None for no code or a code this library does not know yet

Methods:

Name Description
game_message

The game's message for code in lang, if those texts are already loaded.

code instance-attribute

code = code

error instance-attribute

error: GGEError | None = GGEError(code)

game_message

game_message(lang: str = 'en') -> str | None

The game's message for code in lang, if those texts are already loaded.

Never fetches: load them first with empire_core.texts.get_texts. None for no code, texts not loaded, or a code the game has no message for.

Client: CastleHandleServerErrorCommand.performDefaultError (bundle line 120328) shows Localize.text("errorCode_"+code) when that text exists

LoginCooldownError

LoginCooldownError(cooldown: int, message: str = 'Login cooldown active')

Bases: LoginError

Raised when the server rejects login due to rate limiting.

Attributes:

Name Type Description
cooldown

cooldown instance-attribute

cooldown = cooldown

AccountBannedError

AccountBannedError(remaining_seconds: float | None, deleted: bool = False)

Bases: LoginError

Raised when the server refuses the login because the account is banned (IS_BANNED, 27).

Attributes:

Name Type Description
remaining_seconds

seconds until the ban ends (RS), or None

deleted

the account was deleted (GDPR)

Client: LLICommand.executeCommand (bundle line 120651)

remaining_seconds instance-attribute

remaining_seconds = remaining_seconds

deleted instance-attribute

deleted = deleted

WrongServerError

WrongServerError(instance_id: float | None)

Bases: LoginError

Raised when the account belongs to another server (EXISTING_MAPPING_WRONG_SERVER, 368).

Attributes:

Name Type Description
instance_id

the instance id of the account's server (IID), or None; NetworkInstance.instance_id in network.xml

Client: LLICommand.executeCommand (bundle line 120651)

instance_id instance-attribute

instance_id = instance_id

ClientVersionError

ClientVersionError(status: VersionCheckStatus, server_build: str | None)

Bases: LoginError

Raised when the version check (vck) says the client's version is too low or too high.

With EmpireConfig.client_version set, that version is out of date. With it None, the live client's files and the server disagree, usually briefly around a game update, and login(retry=True) and keep_session try again.

Attributes:

Name Type Description
status

VersionCheckStatus.VERSION_TOO_LOW or VERSION_TOO_HIGH

server_build

the server's build number, or None when the reply had none

Client: CastleVCKCommand.executeCommand (bundle line 120444)

status instance-attribute

status = status

server_build instance-attribute

server_build = server_build

PacketError

Bases: EmpireError

Raised when packet parsing fails.

ReplyMismatchError

ReplyMismatchError(expected: int, received: int)

Bases: PacketError

Raised when a reply answers another list than the one asked for, e.g. a late hgh reply.

Attributes:

Name Type Description
expected

the list asked for

received

the list the reply names

expected instance-attribute

expected = expected

received instance-attribute

received = received

EmpireTimeoutError

Bases: EmpireError, TimeoutError

Raised when an operation times out.

Subclasses the builtin TimeoutError so except TimeoutError catches it too.

GameDataNotLoadedError

Bases: EmpireError

Raised when an API needs the static game data and it cannot be loaded.

The APIs load it on first use (GameData.require); this is raised when nothing is loaded and GameData.load failed, with that failure as its cause.

AmbiguousLookupError

AmbiguousLookupError(message: str, ids: list[int])

Bases: EmpireError, LookupError

Raised when a game-data lookup matches more than one row.

Attributes:

Name Type Description
ids

the ids of every matching row, to pick one from the table directly.

ids instance-attribute

ids = ids

EventNotRunningError

EventNotRunningError(event_id: int)

Bases: EmpireError, LookupError

Raised when a call needs an event that is not running: no sei packet named it, or a see ended it.

Attributes:

Name Type Description
event_id

the event looked for

event_id instance-attribute

event_id = event_id

EventHasNoPointsError

EventHasNoPointsError(event_id: int)

Bases: EmpireError, ValueError

Raised when a call needs an event that keeps your rank and points, and the event keeps none.

Attributes:

Name Type Description
event_id

the event asked about, an Event member when the event table has it

event_id instance-attribute

event_id = event_id

NotInAllianceError

NotInAllianceError()

Bases: EmpireError, LookupError

Raised when a call needs your own alliance and the player data names none.

The client reads your alliance from the player data (AID); the server answers a request about your alliance outside one with ALLI_NOT_FOUND.

UnknownCastleError

UnknownCastleError(castle_id: int | None, *, position: tuple[int, int] | None = None)

Bases: EmpireError, ValueError

Raised when a castle is not in the logged-in player's castle list (gcl).

Methods acting on one of your areas send its kingdom, read from the list; the client only offers areas from it.

Attributes:

Name Type Description
castle_id

the castle id looked for, or None when looked for by position

position

the (x, y) looked for, or None when looked for by id

castle_id instance-attribute

castle_id = castle_id

position instance-attribute

position = position

AmbiguousCastleError

AmbiguousCastleError(castle_id: int | None, kingdoms: list[int], *, position: tuple[int, int] | None = None)

Bases: EmpireError, LookupError

Raised when a castle id or position matches your castles in several kingdoms.

The client keeps its castle list per kingdom, so an id could repeat across them; the library then cannot tell which castle is meant.

Attributes:

Name Type Description
castle_id

the castle id looked for, or None when looked for by position

position

the (x, y) looked for, or None when looked for by id

kingdoms

the kingdom id of every match

castle_id instance-attribute

castle_id = castle_id

position instance-attribute

position = position

kingdoms instance-attribute

kingdoms = kingdoms

CommandError

CommandError(command: str, code: int, payload: Any = None)

Bases: EmpireError

Raised when the server responds to a command with a non-zero error code.

Attributes:

Name Type Description
command

the command that failed (e.g. "gaa").

code

the raw numeric status code sent by the server.

error GGEError | None

the matching GGEError member, or None when the server sent a code this library does not know yet. Branch on it instead of on magic numbers:

except CommandError as e:
    if e.error is GGEError.NOT_ENOUGH_RESOURCES:
        ...

GGEError.from_code() deliberately is not used here: it collapses unrecognized codes to GENERAL_ERROR, which would mislabel new server codes as a generic failure.

payload

the error reply's payload when the server sent one. Some commands explain the error in it, e.g. cra for ATTACK_IN_PROGRESS; see CreateAttackResponse.

The message ends with the game's English text for the code, on one line, when those texts are already loaded; game_message gives it as the game has it, in any loaded language.

Methods:

Name Description
game_message

The game's message for code in lang, if those texts are already loaded.

code instance-attribute

code = code

payload instance-attribute

payload = payload

error instance-attribute

error: GGEError | None = GGEError(code)

game_message

game_message(lang: str = 'en') -> str | None

The game's message for code in lang, if those texts are already loaded.

Never fetches: load them first with empire_core.texts.get_texts. None when they are not loaded or the game has no message for the code. Placeholders the client fills for a few codes (a time, a count) stay as {0}.

Client: CastleCommand.showErrorDialog (bundle line 202) hands the code to CastleHandleServerErrorCommand.performDefaultError (bundle line 120328), which shows Localize.text("errorCode_"+code) when that text exists

AttackInProgressError

AttackInProgressError(command: str, code: int, payload: Any = None)

Bases: CommandError

The server refused an attack with ATTACK_IN_PROGRESS (234): one of yours is already on its way there.

The client shows how long until that attack arrives and how big it is, and offers to send anyway, which resends the same attack with FC 1; send_attack(send_anyway=True) does the same.

Attributes:

Name Type Description
arrival_seconds float | None

seconds until the attack already on its way arrives (TS), or None

army_size float | None

the size of that attack (AS), or None

Client: CRACommand.executeCommand, CastlePostPostAttackFactionDialog.onClick.

arrival_seconds instance-attribute

arrival_seconds: float | None = details.get('TS')

army_size instance-attribute

army_size: float | None = details.get('AS')

AttackBelowMinimumError

AttackBelowMinimumError(minimum: int, soldiers: int, attack: Any = None)

Bases: EmpireError, ValueError

An attack's waves carry fewer units than the client lets it send.

The client refuses such an attack with errorCode_100 and the minimum. The server refused one on a player's castle with MOVEMENT_HAS_NO_UNITS (100); whether it enforces the minimum on NPC camps is unverified. Send the error's attack anyway to find out.

Attributes:

Name Type Description
minimum

the fewest units the waves must carry together

soldiers

the units they carry

attack

the filled attack, when fill_attack raised it, else None

Client: AttackDialogStartAttackCheck.onAttack (bundle line 56306).

minimum instance-attribute

minimum = minimum

soldiers instance-attribute

soldiers = soldiers

attack instance-attribute

attack = attack

UnsendableGoodsError

UnsendableGoodsError(message: str, goods: Any)

Bases: EmpireError, ValueError

A market send or kingdom transfer carries goods the client's send dialog would not send.

Attributes:

Name Type Description
goods

the goods as given

Client: CastleSendGoodsDialog.sendGoodsCastle (bundle line 27202), CastleSendGoodsComponent.setTabVisibility (bundle line 44260).

goods instance-attribute

goods = goods

PremiumCommanderCostError

PremiumCommanderCostError(free_premium_commanders: int | None)

Bases: EmpireError, ValueError

A send led by the premium commander may cost rubies, and the caller did not allow it.

The client asks before such a send; pass spend_rubies=True to send it regardless.

Attributes:

Name Type Description
free_premium_commanders

the free premium commanders left, None when not known

Client: CastlePostAttackDialog.startAttack (bundle line 38360) shows CastleBuyTempCommanderDialog when no free premium commander is left.

free_premium_commanders instance-attribute

free_premium_commanders = free_premium_commanders

LoginBonusUnavailableError

LoginBonusUnavailableError(xp: int | None, required_xp: int)

Bases: EmpireError

The login bonus was asked for while your XP is below the client's gate, or not known yet.

The server sends no alb below it (seen live), so a request would only time out.

Attributes:

Name Type Description
xp

your XP from the player data, None before it arrived

required_xp

the XP the client asks for the login bonus from

Client: CastleLoginBonusData.REQUIRED_XP (bundle line 39163), checked by GBDCommand (bundle line 129389) and onUserXpChanged (bundle line 39132) before C2SGetLoginBonusVO

xp instance-attribute

xp = xp

required_xp instance-attribute

required_xp = required_xp

ReceiveThreadError

Bases: EmpireError

Raised when a call that waits for a reply is made on the receive thread.

Packet handlers, Connection.subscribe callbacks and service on_response handlers run on the thread that routes every reply, so a call there that waits could only time out. Hand the work to another thread, or use a GameState callback, which runs on its own callback thread.

MessageUnavailableError

MessageUnavailableError(command: str, code: int, payload: Any = None)

Bases: CommandError

Raised when a message cannot be read: NO_SUCH_MESSAGE or MESSAGEDATA_TOO_OLD (too old to read).

EventStreamOverflowError

Bases: EmpireError

Raised by an EventStream given a maxsize once that many events waited unread: the stream has stopped listening, after the events it holds.

Read the state you need again and open a new stream.