# Errors and recovery

Distinguish retryable request problems from terminal search outcomes in the BirdHouse Matchmaking SDK for Roblox.

Source: https://birdhouse.tech/docs/errors/

The Roblox SDK reports request problems through `client.Error` and terminal search failures through `session.Failed`. A temporary network failure does not immediately end a confirmed search.

## Error shape

```luau
client.Error:Connect(function(problem)
    warn(problem.code, problem.message, problem.retryable)
end)

session.Failed:Connect(function(problem)
    warn("Search failed", session.TicketId, problem.code)
end)
```

Errors include `code`, `message`, and `retryable`. HTTP errors can also include `statusCode` and `details`. Details may contain submitted data, so the SDK does not log them automatically.

## Error reference

| Code | Meaning | What your game should do |
| --- | --- | --- |
| `transport_error` | The HTTP request failed. | Keep the session while the SDK reconciles outstanding work. Check connectivity if persistent. |
| `invalid_response` | The HTTP/progress response could not be read. | Let reconciliation continue; investigate the endpoint and service response. |
| `invalid_result` | A result is missing, has an unexpected ID, or has an unknown state. | Keep the known ticket ID; the SDK retries reconciliation. |
| `invalid_match` | A matched response failed validation. | The SDK retries confirmation. Investigate repeated failures. |
| `http_error` | The service returned an unsuccessful HTTP status. | Inspect `statusCode` and `retryable`; correct rejected input or endpoint configuration. |
| `heartbeat_error` | Processing a heartbeat batch failed. This error is retryable; later batches still run. | Keep active sessions while the SDK retries outstanding work. Investigate repeated failures. |
| `supervisor_error` | The heartbeat supervisor failed. This error is retryable; the loop restarts if active work remains. | Let the client restart its loop and investigate repeated failures. |
| `creation_unresolved` | The attempted creation could not be located during reconciliation. | Treat the session as failed but account for a potentially outstanding original request before replacing it. |
| `ticket_not_found` | A previously accepted ticket expired or was removed. | End the search UI and decide explicitly whether to offer a new search. |
| `client_destroyed` | The client was intentionally destroyed. | Clean up local state; remote work may survive until cancellation or expiry. |

## HTTP retry behavior

HTTP `408`, `429`, and `5xx` responses are retryable. Transport and protocol failures also preserve outstanding work for reconciliation.

For validation rejection statuses `400`, `413`, and `422`, the SDK splits a multi-action batch to isolate the rejected action. A rejected session can fail without blocking valid peers. Other non-retryable HTTP errors end affected sessions.

The SDK processes later batches even if an earlier batch fails. Heartbeats contain at most 100 actions per request.

## Input validation

`CreateSession` validates and copies inputs synchronously. It throws before a session or network work is registered when the party, IDs, metadata, or constraints are invalid.

If queue parameters come from dynamic game state, handle that validation at the boundary:

```luau
local ok, result = pcall(function()
    return client:CreateSession(options)
end)

if not ok then
    warn("Invalid matchmaking options", result)
    return
end

local session = result
-- Connect Matched, Failed, and StateChanged immediately.
```

Do not place `environment` in session options, repeat a player ID in a party, or supply non-JSON metadata. Keep your own party-to-session registry to prevent overlapping searches.

## Lost create responses

The SDK attempts a create with a known GUID, then reconciles that GUID after an ambiguous outcome. It does not blindly repeat creation. If the ticket cannot be found, `creation_unresolved` is terminal for that session.

An original request might still complete after a missing confirmation. Automatically creating a replacement could leave the same players in two searches. Retain `TicketId` and make replacement an explicit part of your game's recovery flow.

## Match handoff failures

A successful match ends the SDK session even if your handler or teleport fails. The SDK does not replay `Matched` when a callback errors.

Retain `session.Match` for game-level retries. Raw clients can confirm the ticket again during the ten-minute result window. Coordinate server reservation and teleport retries in your game so repeated handling of the same match does not create duplicate game sessions.

## Common setup issues

| Symptom | Check |
| --- | --- |
| Wally cannot install the package | Registry access and whether the requested version is released. |
| Requests fail immediately | Roblox HTTP setting, base URL, and deployment reachability. |
| Creates are rejected | Environment allowlist, player ID length, and constraint shapes. |
| A party waits indefinitely | At least two tickets are required; verify party-size combinations and every ticket's rules. |
| Tickets disappear during an outage | Waiting tickets expire after five minutes without a successful confirm. |
| Cancel returns a match | Publication won the cancellation race; handle the valid match. |
