Errors and safe retry
Screen commands​
A screen command returns a ProjectVResult. When IsSuccess is false, show
Message; it is already written for players. The view updates through
Observe, so there is nothing else to render.
var result = await shop.PurchaseAsync(offerId, quantity);
if (this != null && !result.IsSuccess)
{
ShowMessage(result.Message);
}
Presenter commands​
A presenter command returns a ProjectV*CommandResult with IsSuccess and
the latest Snapshot. Render the snapshot, then the error:
var result = await startup.StartAsync(contentReady: true, token);
Render(result.Snapshot);
if (!result.IsSuccess)
{
ShowLocalized(result.Snapshot.Error?.LocalizationKey, result.Snapshot.Error?.RequestId);
}
An exception means a programming mistake (a bad argument, a presenter used from the wrong scene), not a server failure. Do not use exceptions for normal control flow.
What to show​
| The error has | Show |
|---|---|
LocalizationKey (Startup, Authentication, Account, Lobby presenter) | Look it up in the game's localization; fall back to a generic message |
SafeMessage (data screens, Gameplay data) | Show it as is, or map Code to your own text |
Put RequestId in a support or details panel; it lets the SDK team find the
request. Never show or log tokens, passwords or raw server responses.
Cancellation​
Presenter commands take a CancellationToken; tie it to the page, for
example MonoBehaviour.destroyCancellationToken. Screen commands take none:
check that the page still exists before using their result.
Cancelling only stops your wait. It does not undo an action the server may already have applied.
When to retry​
| Situation | Do |
|---|---|
| A first load failed | Offer Retry |
| The server rejected an action | Show the reason; do not resend automatically |
| An action timed out or its result is unknown | Do not send a new one; wait for the screen to update, then let the player decide |
| Mission settlement failed | Keep the result screen open and retry the same completion |
ContractMismatch at startup | Block; the build and the backend do not match |
| Session expired | Go back through Login |
Never resend a purchase, upgrade or claim because the first call timed out, and never write an endless retry loop in a view.
See Troubleshooting for setup and runtime problems.