> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getworkbuddy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Error codes, common issues, and reconnection strategies.

## Error Codes

When an error occurs, the server sends a JSON message with a `code` and `message` field before closing the WebSocket.

| Code                   | Cause                                          | Resolution                                           |
| ---------------------- | ---------------------------------------------- | ---------------------------------------------------- |
| `AUTH_TIMEOUT`         | Token not sent within 10 seconds of connecting | Send the token immediately after the WebSocket opens |
| `INVALID_AUTH`         | First message is missing the token field       | Ensure the first message is `{ "token": "..." }`     |
| `AUTH_FAILED`          | Token is invalid or expired                    | Request a fresh token and reconnect                  |
| `SESSION_SETUP_FAILED` | Server couldn't initialize the voice session   | Retry after a short delay                            |

## WebSocket Close Codes

| Code | Meaning                                                        |
| ---- | -------------------------------------------------------------- |
| 4001 | Authentication timeout — token not sent in time                |
| 4002 | Token required — first message was not valid JSON with a token |
| 4003 | Authentication failed — invalid or expired token               |
| 4500 | Session setup failed — server-side issue                       |
| 1000 | Normal close — agent disconnected or session ended             |

## Common Issues

### Token Expired

Session tokens are valid for **5 minutes**. If you see `AUTH_FAILED`, your token has likely expired. Always request a fresh token immediately before connecting.

### Audio Format Mismatch

The server expects exactly **PCM s16le, 16kHz, mono**. If the AI agent can't understand you, verify your audio encoding matches this spec. Common mistakes:

* Sending Float32 samples instead of Int16
* Wrong sample rate (e.g., 44.1kHz or 48kHz without downsampling)
* Stereo audio instead of mono

### Microphone Not Working (Web)

Browsers require a user gesture (click/tap) before granting mic access. Also check:

* The page is served over HTTPS (or localhost)
* `AudioContext` is resumed after creation — browsers auto-suspend it
* The `ScriptProcessor` output is connected to `ctx.destination` (required to fire)

### Microphone Not Working (Flutter)

Ensure runtime permissions are granted before starting the recorder:

* Android: `RECORD_AUDIO` permission in manifest + runtime request
* iOS: `NSMicrophoneUsageDescription` in Info.plist
* Check `AudioRecorder.hasPermission()` before calling `startStream()`

### WebSocket Connection Refused

Verify the WebSocket URL uses the correct protocol (`wss://` for production, `ws://` for local development). Use the heartbeat endpoint to confirm the API is reachable.

## Reconnection Strategy

Implement exponential backoff when reconnecting after failures:

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function connectWithRetry(maxAttempts = 3) {
    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        await startSession();
        return; // success
      } catch (err) {
        if (attempt === maxAttempts) throw err;
        await new Promise(r => setTimeout(r, attempt * 2000)); // backoff
      }
    }
  }
  ```

  ```dart Dart theme={null}
  Future<void> connectWithRetry({int maxAttempts = 3}) async {
    for (int attempt = 1; attempt <= maxAttempts; attempt++) {
      try {
        await startSession();
        return;
      } catch (e) {
        if (attempt == maxAttempts) rethrow;
        await Future.delayed(Duration(seconds: attempt * 2));
      }
    }
  }
  ```
</CodeGroup>

## API Reference

### POST /api/v1/sdk/token

Creates a voice session and returns a short-lived session token.

```bash theme={null}
# Request
POST /api/v1/sdk/token
Authorization: Bearer <api_key>

# Response 200
{
  "token": "<jwt>",
  "ws_url": "wss://host/api/v1/sdk/ws"
}
```

### POST /api/v1/sdk/heartbeat

Health check — verifies the API is reachable and your API key is valid.

```bash theme={null}
# Request
POST /api/v1/sdk/heartbeat
Authorization: Bearer <api_key>

# Response 200
{ "status": "ok" }
```
