Skip to content

osrlib.errors

The exceptions osrlib raises, and the failures they stand for.

Three different things can go wrong when you call this library, and each has its own answer. Something a player tried that the rules forbid, like walking into a wall or choosing a class their scores don't qualify for, isn't an exception at all. The call returns a refusal, a Rejection, which gives you a code and the facts behind it so you can tell the player why. Something you got wrong in your own code, like an ability score outside 3 to 18 or a seed out of range, raises the stdlib ValueError or TypeError, because that's a bug to fix rather than a state to handle. Everything else raises from the hierarchy here.

That leaves these exceptions for the failures that come from outside the running game: a save file someone truncated or hand-edited, a document written by a newer version of the library than the one reading it, a dice expression that doesn't parse, a command log replayed under different rules. OsrlibError is the base class, so a single except OsrlibError catches all of them, and the three subclasses let you separate the cases that deserve different answers.

Which one you see depends on where you are. Reading a document raises ContentValidationError when the document is malformed and SaveVersionError when it's only too new. Replaying a command log raises ReplayVersionError when the engine underneath has changed. The difference matters: you can't recover from the first, the second means telling the player to upgrade, and the third means loading the save instead of replaying it.

How you report a failure is yours to choose: an HTTP status code, a process exit code, a dialog. The hierarchy grows by addition, so a later version can add an exception type but won't remove or repurpose one, and an except OsrlibError you write today keeps catching everything.

Examples:

from osrlib.errors import OsrlibError, SaveVersionError
from osrlib.versioning import check_document

future = {"kind": "save", "schema_version": 999, "payload": {}}
try:
    check_document(future, "save")
except SaveVersionError as error:
    print(f"too new: {error}")
except OsrlibError:
    print("unreadable")
# too new: document schema_version 999 is newer than the supported 4

ContentValidationError

Bases: OsrlibError

Raised when content handed to the library is malformed.

This is the failure with no repair. Whatever was read can't be understood, so there's nothing to fall back to. Show the message, which names what was wrong, and go no further with that input.

It comes from the boundaries where osrlib accepts something from outside itself:

A document that's well formed but stamped with a newer schema raises SaveVersionError instead, and you can recover from that one by telling the player to upgrade.

OsrlibError

Bases: Exception

The base class every osrlib exception inherits from.

Catch this when you want one handler for anything the library refuses to do, at the edge of a web request or a command-line program, and you don't need to tell the cases apart. Catch a subclass instead when you do. A caller can offer a repair for SaveVersionError and for ReplayVersionError, and none for ContentValidationError.

Nothing raises OsrlibError itself, and don't raise it from your own code. It exists to be caught, and a bare instance tells a handler nothing about what happened.

It doesn't cover a player choice the rules refuse, which comes back as a Rejection rather than being raised, nor a mistake in your own call, which raises the stdlib ValueError or TypeError. Catching OsrlibError alone leaves both of those to travel on, which is what you want.

ReplayVersionError

Bases: OsrlibError

Raised when a command log is replayed under an engine version other than the one that recorded it.

Only replay_game raises it, and only when you pass recorded_engine_version, so you decide whether the check happens at all.

Replay runs the recorded commands again from the same seed and relies on the rules resolving them the same way. A change to those rules can move an outcome, which would make the replayed game differ from the one that was played. Comparing the versions turns that into a failure you can see instead of a difference you can't.

When you catch it, load the save rather than replaying its log. load_game restores the recorded state directly and works across engine versions. Replay is the stricter path, and this is what it trades for that strictness.

SaveVersionError

Bases: OsrlibError

Raised when a document was written by a newer version of osrlib than the one reading it.

Every document osrlib writes includes a schema_version, and check_document compares it against SCHEMA_VERSION before any field is read. A number higher than the running library's means the document can contain shapes this code has never seen, so the read stops there rather than guessing and misreading it.

Catch this separately from ContentValidationError where a player is watching, because it has an answer: the file is fine, the library is behind. Tell them to upgrade osrlib and try again. An older document needs no handling from you, because load_game migrates it forward.

It reaches you from load_game, party_from_document, ContentPack.from_document, and any other reader that calls check_document first.