or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

error-handling.mdevent-client.mdevent-subscriptions.mdindex.mdrequest-client.md

error-handling.mddocs/

0

# Error Handling

1

2

obsws-python provides comprehensive error handling with specific exception types for different failure scenarios. Understanding these errors is crucial for building robust OBS automation applications.

3

4

## Exception Hierarchy

5

6

### Base Exception

7

8

```python { .api }

9

class OBSSDKError(Exception):

10

"""Base class for all OBSSDK errors."""

11

```

12

13

### Specific Exception Types

14

15

```python { .api }

16

class OBSSDKTimeoutError(OBSSDKError):

17

"""

18

Exception raised when a connection times out.

19

20

Raised when:

21

- Connection to OBS WebSocket times out

22

- Request sends but response times out

23

- Event receiving times out

24

"""

25

26

class OBSSDKRequestError(OBSSDKError):

27

"""

28

Exception raised when a request returns an error code.

29

30

Attributes:

31

- req_name (str): Name of the failed request

32

- code (int): OBS WebSocket error code

33

"""

34

35

def __init__(self, req_name, code, comment):

36

self.req_name = req_name

37

self.code = code

38

# message automatically formatted as: "Request {req_name} returned code {code}. With message: {comment}"

39

```

40

41

## Common Error Scenarios

42

43

### Connection Errors

44

45

```python

46

import obsws_python as obs

47

from obsws_python.error import OBSSDKError, OBSSDKTimeoutError

48

49

try:

50

# Wrong host/port

51

client = obs.ReqClient(host='nonexistent', port=9999, timeout=5)

52

except (ConnectionRefusedError, TimeoutError) as e:

53

print(f"Connection failed: {e}")

54

except OBSSDKError as e:

55

print(f"OBS SDK error: {e}")

56

57

try:

58

# Wrong password

59

client = obs.ReqClient(password='wrongpassword')

60

except OBSSDKError as e:

61

print(f"Authentication failed: {e}")

62

63

try:

64

# Connection timeout

65

client = obs.ReqClient(host='slow-server.com', timeout=1)

66

except OBSSDKTimeoutError as e:

67

print(f"Connection timed out: {e}")

68

```

69

70

### Request Errors

71

72

```python

73

import obsws_python as obs

74

from obsws_python.error import OBSSDKRequestError

75

76

client = obs.ReqClient()

77

78

try:

79

# Non-existent scene

80

client.set_current_program_scene("NonExistentScene")

81

except OBSSDKRequestError as e:

82

print(f"Request failed: {e.req_name}")

83

print(f"Error code: {e.code}")

84

print(f"Full error: {e}")

85

86

try:

87

# Invalid input name

88

client.toggle_input_mute("NonExistentInput")

89

except OBSSDKRequestError as e:

90

if e.code == 600: # ResourceNotFound

91

print(f"Input not found: {e.req_name}")

92

else:

93

print(f"Unexpected error {e.code}: {e}")

94

```

95

96

### Event Client Errors

97

98

```python

99

import obsws_python as obs

100

from obsws_python.error import OBSSDKTimeoutError

101

102

try:

103

client = obs.EventClient(timeout=10)

104

105

# Event client runs in background thread

106

# Errors typically occur during connection or event processing

107

108

except OBSSDKTimeoutError as e:

109

print(f"Event client timed out: {e}")

110

except Exception as e:

111

print(f"Event client error: {e}")

112

```

113

114

## Error Codes

115

116

OBS WebSocket returns specific error codes for different failure scenarios:

117

118

### Common Error Codes

119

120

| Code | Name | Description |

121

|------|------|-------------|

122

| 100 | Success | Request completed successfully |

123

| 200 | MissingRequestType | Request type not specified |

124

| 201 | UnknownRequestType | Unknown request type |

125

| 202 | GenericError | Generic error occurred |

126

| 203 | UnsupportedRequestBatchExecutionType | Unsupported batch execution type |

127

| 300 | MissingRequestField | Required request field missing |

128

| 301 | MissingRequestData | Request data missing |

129

| 400 | InvalidRequestField | Invalid request field value |

130

| 401 | InvalidRequestFieldType | Invalid request field type |

131

| 402 | RequestFieldOutOfRange | Request field value out of range |

132

| 403 | RequestFieldEmpty | Request field is empty |

133

| 500 | OutputRunning | Output is running |

134

| 501 | OutputNotRunning | Output is not running |

135

| 502 | OutputPaused | Output is paused |

136

| 503 | OutputNotPaused | Output is not paused |

137

| 504 | OutputDisabled | Output is disabled |

138

| 505 | StudioModeActive | Studio mode is active |

139

| 506 | StudioModeNotActive | Studio mode is not active |

140

| 600 | ResourceNotFound | Resource not found |

141

| 601 | ResourceAlreadyExists | Resource already exists |

142

| 602 | InvalidResourceType | Invalid resource type |

143

| 603 | NotEnoughResources | Not enough resources |

144

| 604 | InvalidResourceState | Invalid resource state |

145

| 605 | InvalidInputKind | Invalid input kind |

146

| 606 | ResourceNotConfigurable | Resource not configurable |

147

| 607 | InvalidFilterKind | Invalid filter kind |

148

149

## Error Handling Patterns

150

151

### Basic Error Handling

152

153

```python

154

import obsws_python as obs

155

from obsws_python.error import OBSSDKError, OBSSDKRequestError, OBSSDKTimeoutError

156

157

def safe_obs_operation(client, operation_name, operation_func):

158

"""

159

Safely execute an OBS operation with error handling.

160

161

Parameters:

162

- client: OBS client instance

163

- operation_name: Description of operation for logging

164

- operation_func: Function to execute

165

166

Returns:

167

- (success: bool, result: any, error: str)

168

"""

169

try:

170

result = operation_func()

171

print(f"βœ… {operation_name} succeeded")

172

return True, result, None

173

174

except OBSSDKRequestError as e:

175

error_msg = f"{operation_name} failed: {e.req_name} returned code {e.code}"

176

print(f"❌ {error_msg}")

177

return False, None, error_msg

178

179

except OBSSDKTimeoutError as e:

180

error_msg = f"{operation_name} timed out: {e}"

181

print(f"⏱️ {error_msg}")

182

return False, None, error_msg

183

184

except OBSSDKError as e:

185

error_msg = f"{operation_name} failed: {e}"

186

print(f"πŸ’₯ {error_msg}")

187

return False, None, error_msg

188

189

# Usage

190

client = obs.ReqClient()

191

192

success, result, error = safe_obs_operation(

193

client,

194

"Scene switch",

195

lambda: client.set_current_program_scene("Scene 2")

196

)

197

198

if success:

199

print("Scene switched successfully")

200

else:

201

print(f"Scene switch failed: {error}")

202

```

203

204

### Retry Logic

205

206

```python

207

import obsws_python as obs

208

from obsws_python.error import OBSSDKTimeoutError, OBSSDKRequestError

209

import time

210

211

def retry_operation(operation_func, max_retries=3, delay=1.0):

212

"""

213

Retry an OBS operation with exponential backoff.

214

215

Parameters:

216

- operation_func: Function to retry

217

- max_retries: Maximum number of retry attempts

218

- delay: Initial delay between retries (doubles each attempt)

219

220

Returns:

221

- Result of successful operation or raises last exception

222

"""

223

last_exception = None

224

225

for attempt in range(max_retries + 1):

226

try:

227

return operation_func()

228

229

except OBSSDKTimeoutError as e:

230

last_exception = e

231

if attempt < max_retries:

232

wait_time = delay * (2 ** attempt)

233

print(f"Timeout on attempt {attempt + 1}, retrying in {wait_time}s...")

234

time.sleep(wait_time)

235

else:

236

print(f"Operation failed after {max_retries + 1} attempts")

237

238

except OBSSDKRequestError as e:

239

# Don't retry request errors (they won't succeed)

240

print(f"Request error (not retrying): {e}")

241

raise

242

243

except OBSSDKError as e:

244

last_exception = e

245

if attempt < max_retries:

246

print(f"Error on attempt {attempt + 1}, retrying...")

247

time.sleep(delay)

248

else:

249

print(f"Operation failed after {max_retries + 1} attempts")

250

251

raise last_exception

252

253

# Usage

254

client = obs.ReqClient()

255

256

try:

257

result = retry_operation(

258

lambda: client.get_version(),

259

max_retries=3,

260

delay=1.0

261

)

262

print(f"Got version: {result.obs_version}")

263

264

except Exception as e:

265

print(f"Failed to get version after retries: {e}")

266

```

267

268

### Context Manager with Error Handling

269

270

```python

271

import obsws_python as obs

272

from obsws_python.error import OBSSDKError

273

from contextlib import contextmanager

274

275

@contextmanager

276

def obs_client_safe(**kwargs):

277

"""

278

Context manager for safe OBS client creation and cleanup.

279

"""

280

client = None

281

try:

282

client = obs.ReqClient(**kwargs)

283

print("βœ… Connected to OBS")

284

yield client

285

286

except OBSSDKError as e:

287

print(f"❌ Failed to connect to OBS: {e}")

288

raise

289

290

finally:

291

if client:

292

try:

293

client.disconnect()

294

print("πŸ”Œ Disconnected from OBS")

295

except Exception as e:

296

print(f"⚠️ Error during disconnect: {e}")

297

298

# Usage

299

try:

300

with obs_client_safe(timeout=10) as client:

301

# Do operations with error handling

302

try:

303

version = client.get_version()

304

print(f"OBS Version: {version.obs_version}")

305

306

client.set_current_program_scene("Scene 1")

307

print("Scene changed successfully")

308

309

except OBSSDKRequestError as e:

310

print(f"Operation failed: {e}")

311

# Continue with other operations...

312

313

except OBSSDKError:

314

print("Could not establish OBS connection")

315

```

316

317

### Event Client Error Handling

318

319

```python

320

import obsws_python as obs

321

from obsws_python.error import OBSSDKError, OBSSDKTimeoutError

322

import threading

323

import time

324

325

class RobustEventClient:

326

def __init__(self, **kwargs):

327

self.client = None

328

self.connection_params = kwargs

329

self.running = False

330

self.reconnect_attempts = 0

331

self.max_reconnects = 5

332

333

def connect(self):

334

"""Connect with error handling and retry logic."""

335

while self.reconnect_attempts < self.max_reconnects:

336

try:

337

if self.client:

338

self.client.disconnect()

339

340

self.client = obs.EventClient(**self.connection_params)

341

self.reconnect_attempts = 0

342

print("βœ… Event client connected")

343

return True

344

345

except OBSSDKTimeoutError as e:

346

self.reconnect_attempts += 1

347

wait_time = min(30, 2 ** self.reconnect_attempts)

348

print(f"⏱️ Connection timeout (attempt {self.reconnect_attempts}), retrying in {wait_time}s...")

349

time.sleep(wait_time)

350

351

except OBSSDKError as e:

352

print(f"❌ Connection failed: {e}")

353

return False

354

355

print(f"πŸ’₯ Failed to connect after {self.max_reconnects} attempts")

356

return False

357

358

def register_callbacks(self, callbacks):

359

"""Register event callbacks with error handling."""

360

if not self.client:

361

print("❌ No client connected")

362

return False

363

364

try:

365

self.client.callback.register(callbacks)

366

return True

367

except Exception as e:

368

print(f"❌ Failed to register callbacks: {e}")

369

return False

370

371

def start_monitoring(self):

372

"""Start monitoring with automatic reconnection."""

373

self.running = True

374

375

def monitor_loop():

376

while self.running:

377

if not self.client or not self.connect():

378

time.sleep(5)

379

continue

380

381

try:

382

# Keep connection alive

383

while self.running:

384

time.sleep(1)

385

386

except Exception as e:

387

print(f"⚠️ Event monitoring error: {e}")

388

self.reconnect_attempts += 1

389

time.sleep(2)

390

391

self.monitor_thread = threading.Thread(target=monitor_loop, daemon=True)

392

self.monitor_thread.start()

393

394

def stop_monitoring(self):

395

"""Stop monitoring and disconnect."""

396

self.running = False

397

if self.client:

398

try:

399

self.client.disconnect()

400

except Exception as e:

401

print(f"⚠️ Error during disconnect: {e}")

402

403

# Usage

404

def on_scene_changed(data):

405

print(f"Scene changed: {data.scene_name}")

406

407

def on_connection_error(error):

408

print(f"Connection error: {error}")

409

410

# Create robust event client

411

event_client = RobustEventClient(

412

host='localhost',

413

port=4455,

414

password='mypassword',

415

timeout=10

416

)

417

418

if event_client.connect():

419

event_client.register_callbacks([on_scene_changed])

420

event_client.start_monitoring()

421

422

try:

423

input("Event monitoring active. Press Enter to stop...\n")

424

finally:

425

event_client.stop_monitoring()

426

else:

427

print("Failed to establish initial connection")

428

```

429

430

## Debugging Tips

431

432

### Enable Logging

433

434

```python

435

import logging

436

import obsws_python as obs

437

438

# Enable debug logging to see raw WebSocket messages

439

logging.basicConfig(level=logging.DEBUG)

440

441

client = obs.ReqClient()

442

# Now you'll see detailed logs of all WebSocket communication

443

```

444

445

### Error Analysis Helper

446

447

```python

448

import obsws_python as obs

449

from obsws_python.error import OBSSDKRequestError

450

451

def analyze_request_error(error):

452

"""Analyze OBS request error and provide helpful information."""

453

if not isinstance(error, OBSSDKRequestError):

454

return f"Not an OBSSDKRequestError: {type(error).__name__}"

455

456

analysis = f"Request: {error.req_name}\nError Code: {error.code}\n"

457

458

# Common error code explanations

459

explanations = {

460

600: "Resource not found - check names are correct and resources exist",

461

601: "Resource already exists - trying to create something that already exists",

462

500: "Output already running - trying to start already active output",

463

501: "Output not running - trying to stop inactive output",

464

505: "Studio mode is active - operation requires studio mode to be disabled",

465

506: "Studio mode not active - operation requires studio mode to be enabled",

466

402: "Value out of range - check parameter bounds",

467

403: "Field is empty - required parameter is missing or empty"

468

}

469

470

if error.code in explanations:

471

analysis += f"Likely cause: {explanations[error.code]}"

472

else:

473

analysis += "Check OBS WebSocket documentation for error code details"

474

475

return analysis

476

477

# Usage

478

client = obs.ReqClient()

479

480

try:

481

client.set_current_program_scene("NonExistentScene")

482

except OBSSDKRequestError as e:

483

print(analyze_request_error(e))

484

```