Documentation

Detailed references

v3 · Preview

Framework v3 is an opt-in preview available to everyone. New games use the stable framework by default.

Builds, limits and errors

validate_code and commit build the game and run its unit tests. This section lists what a build accepts, the errors it answers, the limits of a test run, and the limits of a match.

Source files

  • The crate root is /src/lib.rs. Without it the build fails with bw::no-crate-root.
  • Every other Rust file is a module the crate declares with mod name;: /src/cards.rs for mod cards;, /src/cards/deck.rs for mod deck; inside cards. A file no mod reaches is warning bw::unused-file. A module only the tests declare, such as #[cfg(test)] mod tests;, is reached when the game has a #[test]. The build then compiles the tests too. The build reports bw::unused-file only when the game logic builds without an error and its tests compile.
  • Paths use lowercase letters, digits and _, start with a letter or _, end in .rs, and are at most 8 directories deep.
  • JSON the game logic reads goes in /src/data/. See Data files.
  • The catalog of the game's default locale, such as /src/i18n/en.json, goes into the build too, so msg! can check each message against it (Log lines). A change to it builds the game again. The other locales' catalogs never do.
  • At most 200 files, 256 KiB per file and 2 MiB in total, data files and the default catalog included.

write_file, patch_file and rename_file refuse a .rs path, a data file path or a size the build can never accept, with UNBUILDABLE_RUST_SOURCE. A change to the default catalog that takes the build sources over the file count or the total is refused the same way.

Catalogs

A game's catalogs, /src/i18n/<locale>.json, hold its messages in each locale. Their paths, limits and checks are in Translations.

Crates

A game may use exactly three crates: boardweaver_sdk, serde and serde_json. They are already in scope by name. Use serde's derive through the SDK:

use boardweaver_sdk::serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
#[serde(crate = "boardweaver_sdk::serde")]
struct Hand {
    cards: Vec<String>,
}

There is no Cargo.toml to edit. Write Rust 1.98.1, edition 2024.

Words the build refuses

The build refuses these words anywhere in a .rs file, tests included, even as your own names:

Refused Write instead
static, thread_local Keep the value in the state, or make it a const.
unsafe Safe Rust. The SDK gives a game everything it needs.
extern Nothing: the three crates are already in scope.
env, option_env Another name, such as environment.
include, include_str, include_bytes A data file read with data!, a const in the source, or a module file with mod.
asm, global_asm, naked_asm Rust.

Also refused: mod inside a macro, #[path], #[should_panic], crate-level #![...] attributes other than allow, warn, deny, forbid, expect and doc, and brackets nested deeper than 256. The 'static lifetime is allowed.

Reading a build error

validate_code answers errors and warnings as text in the Rust compiler's format, with paths as you wrote them:

error[bw::refused]: a game may not declare a `static`
 --> /src/lib.rs:12:1
   |
12 | static COUNT: u32 = 0;
   | ^^^^^^
   = help: A game is a pure function of its state, the action and the seed, so nothing may outlive a call. Keep the value in a field of the match's state, or use a `const` or a function; for a lookup table, build a `BTreeMap` where you need it rather than caching it

Every bw::refused error ends with a help line that says what to write instead.

A failed commit answers BUILD_FAILED with the first 20 errors. Fix them from the top: later errors often follow from the first.

Code Means
E...., a lint name the Rust compiler's own error or warning
bw::refused a refused word, above
bw::lex a file does not read as Rust tokens
bw::no-crate-root no /src/lib.rs
bw::unused-file a file no mod reaches (warning)
bw::read-outside-source the code refers to a file outside the game's .rs and data files
bw::data-json a data file is not JSON (Data files)
bw::module-too-large the built game is over 4 MiB
bw::bad-module the built game exports no game: check for export_game!
bw::test-failed a unit test panicked or returned an Err; the error points at the panic's line and quotes its message (Testing a game)
bw::test-fuel a unit test used all its computation, or the tests used all of theirs and the rest did not finish, below
bw::test-trap a unit test stopped another way, such as running out of memory, or the tests ran out of time, below
bw::too-many-tests the game logic has more than 200 unit tests, or their names are over 256 KiB, so none ran
bw::client-types the types listed in client_types! do not read, or their JSON Schema is over 512 KiB; the message names the problem, such as two types sharing one name or a type that refers to one no client_types! defines (Client types)
bw::time-limit the build ran past its time limit
bw::memory-limit the build ran out of memory
bw::truncated more than 200 diagnostics; only the first are shown

Tool errors

Code Tool Means
INVALID_IMAGE upload_art, upload_marketing_image The image data is incomplete or unreadable. Upload a complete JPEG or PNG file.
GAME_NOT_FOUND every tool whose input requires gameDefinitionId, and save_checkpoint The game does not exist, was deleted, or your role on it does not reach the tool. Boardweaver gives all three the same answer.
UNBUILDABLE_RUST_SOURCE write_file, patch_file, rename_file A .rs path, a data file path or a size the build cannot accept, the default catalog's included.
INVALID_CATALOG write_file, patch_file, rename_file A catalog Boardweaver could never use (Catalogs). The message names the file and why.
BUILD_FAILED commit, start_game The game logic did not build, a unit test failed, or a client type's name cannot be exported from boardweaver/game (Client types). For commit only, the client did not build, or a catalog cannot be used (Catalogs).
CATALOG_PLACEHOLDERS_MISMATCH commit A translation's message places other placeholders, tags or select keys than the same message in the default catalog (Translations). The message names each file, key and both sets of placeholders. Nothing was built.
BUILD_BUSY validate_code, commit, start_game Boardweaver is building other games. Try again after the time it names.
BUILD_UNAVAILABLE validate_code, commit, start_game Boardweaver cannot build games right now. Try again later.
NOT_CONFIGURED validate_code, commit, start_game This Boardweaver environment cannot build games.
TYPE_CHECK_BUSY validate_code Boardweaver is type-checking other games. Nothing changed. Try again in a moment.
INVALID_STATE start_game, set_state The state is not one a session can hold. The message names each problem.
INVALID_ACTION apply_action The action is not a v3 action. Copy one offer's action.
ACTION_REFUSED apply_action Boardweaver or the game refused a step, for the reason the message gives. Nothing changed.
DECISION_IN_PROGRESS apply_action Another player has an open decision. End it, or drop it with set_state.
INIT_FAILED, APPLY_FAILED, REFRESH_FAILED start_game, apply_action, set_state The game logic failed, for example with a panic or a timeout. The message has what the game printed.
GAME_RUNNER_UNAVAILABLE start_game, apply_action, set_state Boardweaver cannot reach its game runner. Nothing changed. Try again in a minute.
GAME_RUNNER_BUSY start_game, apply_action, set_state Boardweaver's game runner is busy with other games. Nothing changed. Try again in a moment.
SESSION_CHANGED apply_action, set_state Another call changed the session while this one ran, so this call changed nothing. Read it with inspect_state, then try again.
RENDER_UNSUPPORTED render_game The session has no client to render: it did not build, or the game has none. start_game's warnings says which.
LOCALE_NOT_IN_GAME start_game, render_game locale is not the game's default locale, a locale it has a catalog for, or en-XA. Write /src/i18n/<locale>.json, then start a new session.
RENDER_TOO_LARGE render_game The HTML and CSS are over 100,000 characters together, so the answer holds neither. Render with format: "image".
UNSUPPORTED_ON_THIS_VERSION save_checkpoint, start_game, set_state, render_game The tool does not take a v3 session, or start_game or set_state was given validateTypes. On a framework v1 or v2 game, start_game and render_game answer it for locale.

Test limits

Every build runs the unit tests with these limits:

Limit Value When it is hit
Tests 200, with names of at most 256 KiB in all bw::too-many-tests, and no test runs
Computation per test 10,000,000,000 units of fuel, about one per WebAssembly instruction. play_bots keeps its bots to half of it (Testing a bot) bw::test-fuel
Computation for all the tests 40,000,000,000 units bw::test-fuel, and the rest do not finish
Memory per test 50 MiB, as in a match bw::test-trap
Time the whole build, tests included, ends 140 seconds after it starts bw::test-trap, and the rest do not run

bw::test-fuel names the test that ran out. Every step a test applies, and every bot call, uses fuel. Play fewer decisions or fewer games in that test, or split it into several tests.

Limits in a match

Each call to a game function has these limits:

Limit Value When it is hit
Memory 50 MiB GAME_FAILED
Computation a fixed budget per call, which a long loop or a deep search can use up EXECUTION_TIMEOUT
Time about 4 seconds per call EXECUTION_TIMEOUT
State 1 MiB as JSON GAME_FAILED
The offers and changes of one call 2 MiB as JSON GAME_FAILED
Log lines of one step, or of the opening 32 lines and 8 KiB as JSON for all of them GAME_FAILED: table.log panics
A message: a log line's, an offer's label or a refusal's reason a key of 1 to 128 bytes, messages nested at most 8 deep, no value named player, and only seated players GAME_FAILED: table.log, the offers or the refusal panics

A panic in the game logic is GAME_FAILED, with the panic message and any text the game logic printed. Each failure is recorded as a match error, which the game's studio lists.

The Errors page groups game failures so a designer can inspect affected sessions.
The Errors page groups game failures so a designer can inspect affected sessions. Example data from the local development UI. Select the image to enlarge.

Need a hand with this?

Join our Discord