or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

clients.mdconfiguration.mddata-models.mdexceptions.mdindex.mdmodels.mdrequest-functions.md

exceptions.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy for handling different types of HTTP errors, timeouts, connection issues, and protocol violations. HTTP3 provides specific exception types that enable precise error handling and appropriate recovery strategies.

3

4

## Capabilities

5

6

### Timeout Exceptions

7

8

Exceptions related to various timeout scenarios during HTTP operations.

9

10

```python { .api }

11

class Timeout(Exception):

12

"""

13

Base class for all timeout exceptions.

14

15

All timeout-related exceptions inherit from this class, allowing

16

you to catch any timeout condition with a single except block.

17

"""

18

19

class ConnectTimeout(Timeout):

20

"""

21

Timeout while establishing a connection.

22

23

Raised when the client cannot establish a TCP connection to the

24

server within the specified connect_timeout period.

25

"""

26

27

class ReadTimeout(Timeout):

28

"""

29

Timeout while reading response data.

30

31

Raised when the server doesn't send response data within the

32

specified read_timeout period after connection is established.

33

"""

34

35

class WriteTimeout(Timeout):

36

"""

37

Timeout while writing request data.

38

39

Raised when the client cannot send request data to the server

40

within the specified write_timeout period.

41

"""

42

43

class PoolTimeout(Timeout):

44

"""

45

Timeout while waiting to acquire a connection from the pool.

46

47

Raised when no connection becomes available in the connection

48

pool within the specified pool_timeout period.

49

"""

50

```

51

52

**Usage Example:**

53

54

```python

55

import http3

56

57

try:

58

response = http3.get('https://slow-server.example.com', timeout=5.0)

59

except http3.ConnectTimeout:

60

print("Could not connect to server")

61

except http3.ReadTimeout:

62

print("Server didn't respond in time")

63

except http3.WriteTimeout:

64

print("Could not send request data")

65

except http3.PoolTimeout:

66

print("No connection available in pool")

67

except http3.Timeout:

68

print("Some kind of timeout occurred")

69

```

70

71

### HTTP Protocol Exceptions

72

73

Exceptions related to HTTP protocol violations and general HTTP errors.

74

75

```python { .api }

76

class ProtocolError(Exception):

77

"""

78

Malformed HTTP protocol data.

79

80

Raised when the server sends invalid HTTP data that violates

81

the HTTP specification, such as malformed headers or invalid

82

response structure.

83

"""

84

85

class DecodingError(Exception):

86

"""

87

Content decoding failure.

88

89

Raised when response content cannot be decoded properly,

90

such as invalid UTF-8 encoding or corrupted compressed data.

91

"""

92

93

class InvalidURL(Exception):

94

"""

95

Invalid URL format.

96

97

Raised when a provided URL is malformed, missing required

98

components (scheme, host), or contains invalid characters.

99

"""

100

```

101

102

**Usage Example:**

103

104

```python

105

import http3

106

107

try:

108

response = http3.get('invalid://url')

109

except http3.InvalidURL:

110

print("URL format is invalid")

111

112

try:

113

response = http3.get('https://api.example.com/data')

114

data = response.json()

115

except http3.ProtocolError:

116

print("Server sent malformed HTTP data")

117

except http3.DecodingError:

118

print("Could not decode response content")

119

```

120

121

### Redirect Exceptions

122

123

Exceptions related to HTTP redirect handling and redirect loops.

124

125

```python { .api }

126

class TooManyRedirects(Exception):

127

"""

128

Too many redirects occurred.

129

130

Raised when the number of redirects exceeds the maximum

131

allowed limit (typically 20 by default).

132

"""

133

134

class RedirectBodyUnavailable(Exception):

135

"""

136

Redirect attempted but request body was streaming and is no longer available.

137

138

Raised when a POST/PUT request with streaming body encounters

139

a redirect, but the body cannot be replayed for the redirect.

140

"""

141

142

class RedirectLoop(Exception):

143

"""

144

Infinite redirect loop detected.

145

146

Raised when the client detects that redirects are forming

147

a loop, visiting the same URLs repeatedly.

148

"""

149

```

150

151

**Usage Example:**

152

153

```python

154

import http3

155

156

try:

157

response = http3.get('https://example.com/redirect-loop')

158

except http3.TooManyRedirects:

159

print("Too many redirects - possible redirect loop")

160

except http3.RedirectLoop:

161

print("Infinite redirect loop detected")

162

163

try:

164

with open('large-file.bin', 'rb') as f:

165

response = http3.post('https://example.com/upload', data=f)

166

except http3.RedirectBodyUnavailable:

167

print("Cannot redirect streaming request body")

168

```

169

170

### Stream Exceptions

171

172

Exceptions related to response streaming and content access patterns.

173

174

```python { .api }

175

class StreamConsumed(Exception):

176

"""

177

Attempted to read or stream response content that has already been consumed.

178

179

Raised when trying to access response content after it has

180

already been read through streaming or direct access.

181

"""

182

183

class ResponseNotRead(Exception):

184

"""

185

Attempted to access response content without reading it first.

186

187

Raised when trying to access response content properties

188

after a streaming response that hasn't been fully read.

189

"""

190

191

class ResponseClosed(Exception):

192

"""

193

Attempted to read or stream response content from a closed response.

194

195

Raised when trying to access content from a response that

196

has been explicitly closed or whose connection was terminated.

197

"""

198

```

199

200

**Usage Example:**

201

202

```python

203

import http3

204

205

try:

206

response = http3.get('https://api.example.com/data', stream=True)

207

208

# Consume the stream

209

for chunk in response.iter_content():

210

process_chunk(chunk)

211

212

# This will raise StreamConsumed

213

text = response.text

214

215

except http3.StreamConsumed:

216

print("Response content already consumed")

217

except http3.ResponseNotRead:

218

print("Response not fully read")

219

except http3.ResponseClosed:

220

print("Response connection closed")

221

```

222

223

### Connection Exceptions

224

225

Exceptions related to connection management and network issues.

226

227

```python { .api }

228

class NotConnected(Exception):

229

"""

230

Connection was lost at the point of starting a request.

231

232

Raised when a connection is lost before any request data

233

has been successfully sent.

234

"""

235

236

class CookieConflict(Exception):

237

"""

238

Attempted to lookup a cookie by name, but multiple cookies existed.

239

240

Raised when trying to access a cookie by name when multiple

241

cookies with the same name exist for different domains/paths.

242

"""

243

```

244

245

## Error Handling Strategies

246

247

### Comprehensive Error Handling

248

249

```python

250

import http3

251

import time

252

253

def robust_request(url, max_retries=3, backoff_factor=1.0):

254

"""Make a request with comprehensive error handling and retries."""

255

256

for attempt in range(max_retries):

257

try:

258

response = http3.get(url, timeout=30.0)

259

response.raise_for_status() # Raise for HTTP error status codes

260

return response

261

262

except http3.ConnectTimeout:

263

print(f"Connection timeout (attempt {attempt + 1})")

264

if attempt < max_retries - 1:

265

time.sleep(backoff_factor * (2 ** attempt))

266

continue

267

raise

268

269

except http3.ReadTimeout:

270

print(f"Read timeout (attempt {attempt + 1})")

271

if attempt < max_retries - 1:

272

time.sleep(backoff_factor * (2 ** attempt))

273

continue

274

raise

275

276

except http3.ProtocolError as e:

277

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

278

# Don't retry protocol errors

279

raise

280

281

except http3.TooManyRedirects:

282

print("Too many redirects")

283

# Don't retry redirect errors

284

raise

285

286

except http3.InvalidURL as e:

287

print(f"Invalid URL: {e}")

288

# Don't retry URL errors

289

raise

290

291

except Exception as e:

292

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

293

if attempt < max_retries - 1:

294

time.sleep(backoff_factor * (2 ** attempt))

295

continue

296

raise

297

298

# Usage

299

try:

300

response = robust_request('https://api.example.com/data')

301

data = response.json()

302

except http3.Timeout:

303

print("Request timed out after retries")

304

except http3.ProtocolError:

305

print("Server sent invalid HTTP data")

306

except Exception as e:

307

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

308

```

309

310

### Async Error Handling

311

312

```python

313

import http3

314

import asyncio

315

316

async def async_request_with_handling(url):

317

"""Async request with proper error handling."""

318

319

try:

320

async with http3.AsyncClient(timeout=30.0) as client:

321

response = await client.get(url)

322

323

# Check for HTTP errors

324

if response.is_error:

325

print(f"HTTP Error: {response.status_code}")

326

return None

327

328

return await response.json()

329

330

except http3.ConnectTimeout:

331

print("Could not connect to server")

332

except http3.ReadTimeout:

333

print("Server response timeout")

334

except http3.ProtocolError as e:

335

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

336

except http3.DecodingError as e:

337

print(f"Content decoding error: {e}")

338

except Exception as e:

339

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

340

341

return None

342

343

# Usage

344

async def main():

345

data = await async_request_with_handling('https://api.example.com/data')

346

if data:

347

print(f"Received data: {data}")

348

349

asyncio.run(main())

350

```

351

352

### Context-Specific Error Handling

353

354

```python

355

import http3

356

357

def handle_api_request(url, api_key):

358

"""Handle API requests with context-specific error handling."""

359

360

try:

361

response = http3.get(

362

url,

363

headers={'Authorization': f'Bearer {api_key}'},

364

timeout=10.0

365

)

366

367

# Handle HTTP status codes

368

if response.status_code == 401:

369

raise AuthenticationError("Invalid API key")

370

elif response.status_code == 429:

371

raise RateLimitError("Rate limit exceeded")

372

elif response.status_code >= 500:

373

raise ServerError(f"Server error: {response.status_code}")

374

375

response.raise_for_status()

376

return response.json()

377

378

except http3.ConnectTimeout:

379

raise NetworkError("Cannot connect to API server")

380

except http3.ReadTimeout:

381

raise NetworkError("API server response timeout")

382

except http3.InvalidURL:

383

raise ConfigurationError("Invalid API URL")

384

except http3.DecodingError:

385

raise DataError("Invalid response format")

386

387

# Custom exception hierarchy

388

class APIError(Exception):

389

"""Base API error."""

390

391

class NetworkError(APIError):

392

"""Network-related error."""

393

394

class AuthenticationError(APIError):

395

"""Authentication error."""

396

397

class RateLimitError(APIError):

398

"""Rate limit error."""

399

400

class ServerError(APIError):

401

"""Server error."""

402

403

class ConfigurationError(APIError):

404

"""Configuration error."""

405

406

class DataError(APIError):

407

"""Data processing error."""

408

```

409

410

### Response Streaming Error Handling

411

412

```python

413

import http3

414

415

def download_file_with_error_handling(url, filename):

416

"""Download a file with proper streaming error handling."""

417

418

try:

419

response = http3.get(url, stream=True)

420

response.raise_for_status()

421

422

with open(filename, 'wb') as f:

423

try:

424

for chunk in response.iter_content(chunk_size=8192):

425

f.write(chunk)

426

427

except http3.ReadTimeout:

428

print("Download interrupted - read timeout")

429

response.close()

430

# Remove partial file

431

import os

432

if os.path.exists(filename):

433

os.remove(filename)

434

raise

435

436

except http3.StreamConsumed:

437

print("Stream already consumed")

438

raise

439

440

except http3.ResponseClosed:

441

print("Connection closed during download")

442

raise

443

444

print(f"Downloaded {filename} successfully")

445

446

except http3.ConnectTimeout:

447

print("Could not connect to download server")

448

except http3.ProtocolError:

449

print("Invalid response from server")

450

except Exception as e:

451

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

452

# Clean up partial file

453

import os

454

if os.path.exists(filename):

455

os.remove(filename)

456

raise

457

458

# Usage

459

try:

460

download_file_with_error_handling(

461

'https://example.com/large-file.zip',

462

'downloaded-file.zip'

463

)

464

except Exception:

465

print("Download failed")

466

```

467

468

## Exception Hierarchy Summary

469

470

```

471

Exception

472

├── Timeout

473

│ ├── ConnectTimeout

474

│ ├── ReadTimeout

475

│ ├── WriteTimeout

476

│ └── PoolTimeout

477

├── ProtocolError

478

├── DecodingError

479

├── InvalidURL

480

├── TooManyRedirects

481

├── RedirectBodyUnavailable

482

├── RedirectLoop

483

├── StreamConsumed

484

├── ResponseNotRead

485

├── ResponseClosed

486

├── NotConnected

487

└── CookieConflict

488

```

489

490

This hierarchy allows for both specific and general exception handling patterns depending on your application's needs.