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, every error code an agent can meet, the limits of a test run, and the limits of a match.

Studio code editor

The Rust Code tab shows source files, build status, and warnings with source locations.
The Rust Code tab shows source files, build status, and warnings with source locations. Example data from the local development UI. Select the image to enlarge.

The studio's Code tab highlights Rust and saves each file automatically. After a save, Boardweaver builds the game logic, runs its unit tests, and bundles the client against the generated game types.

The build strip shows pending changes, running builds, errors and warnings. Expand it to read the diagnostics. Select a diagnostic with a file location to open that file. When Boardweaver cannot build, the strip shows a build error.

The editor does not let you rename or delete /src/lib.rs or /src/frontend.tsx. Create, rename and delete other Rust modules under /src/. The editor has no Rust autocomplete or formatting.

Run validate_code before you commit: only it type-checks the client.

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. The build reports it only when the game logic builds without an error and its tests compile.
  • A module only the tests declare, such as #[cfg(test)] mod tests;, counts as reached when the game has a #[test]. The build then compiles the tests too.
  • A .rs path uses lowercase letters, digits and _, starts each name with a letter or _, and sits at most 7 directories below /src/.
  • JSON the game logic reads goes in /src/data/ (Data files).
  • The build also reads the catalog of the game's default locale, such as /src/i18n/en.json, so it can check each msg! against it (Log lines). A change to that catalog builds the game again. A change to another locale's catalog does not.
  • The build takes 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 change the build could never accept, with UNBUILDABLE_RUST_SOURCE: a .rs or data file path outside these rules, or a file, file count or total over these limits. A change to the default catalog counts toward the limits too.

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 uses 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.

The build also refuses 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 word or construct the build refuses (Words the build refuses)
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 (Test limits)
bw::test-trap a unit test stopped another way, such as running out of memory, or the tests ran out of time (Test limits)
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 checking and compiling took over 180 seconds, or the whole build ran past 290 seconds
bw::memory-limit the build used more than its 1 GiB of memory
bw::truncated more than 200 diagnostics; only the first are shown

Tool errors

Code Tool Means
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 The change gives a .rs path, a data file path or a size the build can never accept, the default catalog's included (Source files). Nothing changed.
INVALID_CATALOG write_file, patch_file, rename_file A catalog Boardweaver could never use (Catalogs). The message names the file and why.
INVALID_THEME_JSON write_file, patch_file /theme.json is not JSON.
INVALID_THEME write_file, patch_file /theme.json does not fit the theme's fields (Design the theme). The message names each wrong field.
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, a catalog cannot be used, the default locale has no catalog, or a bot's text does not read (Translations). validate_code lists the same problems as errors.
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.
SOURCE_CHANGED commit A Rust file, a data file, a catalog, the default locale or the framework changed while the game built, so nothing was committed. Commit again.
BUILD_TOO_NEW commit Boardweaver is part way through an update. Commit again shortly.
RULES_COMPILE_FAILED commit A rules page did not compile. The message lists each problem, with its file and node (Write the rules pages).
MARKETING_COMPILE_FAILED commit A marketing page did not compile, and every rules page did. The message lists each problem (Write the marketing page).
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_PLAYER_COUNT start_game numPlayers is not one of the game's validPlayerCounts, or differs from the number of players in state.
INVALID_STATE start_game, set_state The state is not one a session can hold. The message names each problem.
INVALID_PATH set_state An update's path does not reach a place in the state.
STATE_NOT_FOUND apply_action, inspect_state, set_state, render_game, save_checkpoint The session does not exist or has expired. Start a new one with start_game.
INVALID_PLAYER apply_action, inspect_state, render_game The player is not seated in this session. The message lists the seats.
INVALID_ACTION apply_action The action is not one an offer gives. 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, save_checkpoint A decision is open: another player's, for apply_action, or any, for save_checkpoint. End it with an offer whose intent is confirm, 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 run the game right now. Nothing changed. Try again in a minute.
GAME_RUNNER_BUSY start_game, apply_action, set_state Boardweaver is running too many 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 the session with inspect_state, then try again.
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.
UNSUPPORTED_ON_THIS_VERSION start_game, set_state validateTypes was passed. A session checks the state against the SDK's state schema, so leave validateTypes out.
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.
RENDER_TOO_LARGE render_game The HTML and CSS are over 100,000 characters together, so the answer holds neither. Render with format: "image". Or the screenshot is over 3,932,160 bytes, so the answer holds no image. Render with a smaller viewport.
RENDER_FAILED render_game The client could not start or render. The message says why.
UNKNOWN_EXAMPLE get_example Choose a name from the examples listed in the answer.
UNKNOWN_EXAMPLE_FILE get_example Call without path for the guide, then copy a file path from its list.
INVALID_IMAGE upload_art, upload_marketing_image The image data is incomplete or unreadable. Upload a complete JPEG or PNG file.
INVALID_UPLOAD_SIZE create_upload The byte length is over the destination's limit, or a media file is empty.
UPLOAD_NOT_CONFIGURED create_upload This Boardweaver environment cannot sign uploads. Pass the file to the upload tool's url or data instead.
INVALID_UPLOAD_URL, UPLOAD_ALREADY_USED signed upload HTTP endpoint Request a new URL with create_upload.
UPLOAD_SIZE_MISMATCH, UPLOAD_HASH_MISMATCH signed upload HTTP endpoint Send the exact original bytes, or request a URL for the new file.
INVALID_UPLOAD_CONTENT_TYPE, INVALID_UPLOAD_TEXT signed upload HTTP endpoint Send raw bytes as application/octet-stream. Text must be valid UTF-8.
UPLOAD_ABORTED, UPLOAD_TIMEOUT signed upload HTTP endpoint Send the complete file again before the URL expires.
UPLOAD_METHOD_NOT_ALLOWED signed upload HTTP endpoint Use POST.

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, more than a match has (Limits in a match), so a passing test does not prove a match fits bw::test-trap
Time the whole build, tests included, ends 280 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 16 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. Boardweaver records each failure as a match error, which the game's studio lists.

The Errors page lists the newest failures in matches of your game.
The Errors page lists the newest failures in matches of your game. Example data from the local development UI. Select the image to enlarge.

Need a hand with this?

Join our Discord