or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

applications.mdcli.mdexceptions.mdindex.mdoperation-resolution.mdrequest-response.mdsecurity.mdvalidation.md

exceptions.mddocs/

0

# Exception Handling

1

2

Comprehensive exception system following RFC 7807 Problem Details standard for consistent error responses and debugging. Connexion provides both generic exceptions and HTTP-specific problem exceptions.

3

4

## Capabilities

5

6

### Base Exceptions

7

8

Core exception classes for Connexion-specific errors.

9

10

```python { .api }

11

class ConnexionException(Exception):

12

"""Base exception class for all Connexion-specific errors"""

13

pass

14

15

class ResolverError(ConnexionException):

16

"""Raised when operation resolution fails"""

17

def __init__(self, reason: str, operation_id: str = None):

18

"""

19

Initialize resolver error.

20

21

Parameters:

22

- reason: Description of the resolution failure

23

- operation_id: Failed operation identifier

24

"""

25

26

class InvalidSpecification(ConnexionException):

27

"""Raised when OpenAPI specification is invalid"""

28

def __init__(self, reason: str, spec_path: str = None):

29

"""

30

Initialize specification error.

31

32

Parameters:

33

- reason: Description of the specification issue

34

- spec_path: Path to the invalid specification

35

"""

36

37

class UnsupportedMediaTypeProblem(ConnexionException):

38

"""Raised when request contains unsupported media type"""

39

def __init__(self, media_type: str, supported_types: list = None):

40

"""

41

Initialize media type error.

42

43

Parameters:

44

- media_type: Unsupported media type

45

- supported_types: List of supported media types

46

"""

47

```

48

49

### Problem Exception Base

50

51

RFC 7807 Problem Details implementation for HTTP API errors.

52

53

```python { .api }

54

class ProblemException(Exception):

55

"""

56

Base class for RFC 7807 Problem Detail exceptions.

57

Automatically generates appropriate HTTP error responses.

58

"""

59

60

def __init__(

61

self,

62

status: int,

63

title: str,

64

detail: str = None,

65

type: str = None,

66

instance: str = None,

67

**kwargs

68

):

69

"""

70

Initialize problem exception.

71

72

Parameters:

73

- status: HTTP status code

74

- title: Short, human-readable problem summary

75

- detail: Human-readable explanation specific to this occurrence

76

- type: URI that identifies the problem type

77

- instance: URI that identifies the specific occurrence

78

- **kwargs: Additional problem-specific properties

79

"""

80

super().__init__(detail or title)

81

self.status = status

82

self.title = title

83

self.detail = detail

84

self.type = type

85

self.instance = instance

86

self.extra = kwargs

87

88

def to_problem(self) -> dict:

89

"""

90

Convert exception to RFC 7807 problem dict.

91

92

Returns:

93

dict: Problem details response

94

"""

95

```

96

97

### HTTP Client Error Exceptions (4xx)

98

99

Exceptions for client-side errors with automatic HTTP status codes.

100

101

```python { .api }

102

class BadRequestProblem(ProblemException):

103

"""400 Bad Request - Client sent invalid request"""

104

def __init__(self, title: str = "Bad Request", **kwargs):

105

super().__init__(status=400, title=title, **kwargs)

106

107

class UnauthorizedProblem(ProblemException):

108

"""401 Unauthorized - Authentication required or failed"""

109

def __init__(self, title: str = "Unauthorized", **kwargs):

110

super().__init__(status=401, title=title, **kwargs)

111

112

class ForbiddenProblem(ProblemException):

113

"""403 Forbidden - Access denied"""

114

def __init__(self, title: str = "Forbidden", **kwargs):

115

super().__init__(status=403, title=title, **kwargs)

116

117

class NotFoundProblem(ProblemException):

118

"""404 Not Found - Resource not found"""

119

def __init__(self, title: str = "Not Found", **kwargs):

120

super().__init__(status=404, title=title, **kwargs)

121

122

class MethodNotAllowedProblem(ProblemException):

123

"""405 Method Not Allowed - HTTP method not supported"""

124

def __init__(self, title: str = "Method Not Allowed", **kwargs):

125

super().__init__(status=405, title=title, **kwargs)

126

127

class NotAcceptableProblem(ProblemException):

128

"""406 Not Acceptable - Cannot generate acceptable response"""

129

def __init__(self, title: str = "Not Acceptable", **kwargs):

130

super().__init__(status=406, title=title, **kwargs)

131

132

class ConflictProblem(ProblemException):

133

"""409 Conflict - Request conflicts with current state"""

134

def __init__(self, title: str = "Conflict", **kwargs):

135

super().__init__(status=409, title=title, **kwargs)

136

137

class UnsupportedMediaTypeProblem(ProblemException):

138

"""415 Unsupported Media Type - Request media type not supported"""

139

def __init__(self, title: str = "Unsupported Media Type", **kwargs):

140

super().__init__(status=415, title=title, **kwargs)

141

142

class UnprocessableEntityProblem(ProblemException):

143

"""422 Unprocessable Entity - Request is well-formed but semantically incorrect"""

144

def __init__(self, title: str = "Unprocessable Entity", **kwargs):

145

super().__init__(status=422, title=title, **kwargs)

146

```

147

148

### HTTP Server Error Exceptions (5xx)

149

150

Exceptions for server-side errors.

151

152

```python { .api }

153

class InternalServerErrorProblem(ProblemException):

154

"""500 Internal Server Error - Unexpected server error"""

155

def __init__(self, title: str = "Internal Server Error", **kwargs):

156

super().__init__(status=500, title=title, **kwargs)

157

158

class NotImplementedProblem(ProblemException):

159

"""501 Not Implemented - Functionality not implemented"""

160

def __init__(self, title: str = "Not Implemented", **kwargs):

161

super().__init__(status=501, title=title, **kwargs)

162

163

class ServiceUnavailableProblem(ProblemException):

164

"""503 Service Unavailable - Service temporarily unavailable"""

165

def __init__(self, title: str = "Service Unavailable", **kwargs):

166

super().__init__(status=503, title=title, **kwargs)

167

```

168

169

### Validation Exceptions

170

171

Exceptions specifically for validation failures.

172

173

```python { .api }

174

class ValidationError(BadRequestProblem):

175

"""Request validation failure"""

176

def __init__(self, detail: str, field: str = None, **kwargs):

177

"""

178

Initialize validation error.

179

180

Parameters:

181

- detail: Validation failure description

182

- field: Field that failed validation

183

- **kwargs: Additional validation context

184

"""

185

super().__init__(

186

title="Validation Error",

187

detail=detail,

188

field=field,

189

**kwargs

190

)

191

192

class TypeValidationError(ValidationError):

193

"""Type validation failure"""

194

def __init__(self, field: str, expected_type: str, actual_type: str, **kwargs):

195

"""

196

Initialize type validation error.

197

198

Parameters:

199

- field: Field with type error

200

- expected_type: Expected data type

201

- actual_type: Actual data type received

202

"""

203

super().__init__(

204

detail=f"Field '{field}' expected {expected_type}, got {actual_type}",

205

field=field,

206

expected_type=expected_type,

207

actual_type=actual_type,

208

**kwargs

209

)

210

211

class ExtraParameterProblem(ValidationError):

212

"""Extra parameter in request"""

213

def __init__(self, param_name: str, **kwargs):

214

"""

215

Initialize extra parameter error.

216

217

Parameters:

218

- param_name: Name of the unexpected parameter

219

"""

220

super().__init__(

221

detail=f"Extra parameter '{param_name}' not allowed",

222

parameter=param_name,

223

**kwargs

224

)

225

```

226

227

## Usage Examples

228

229

### Basic Exception Handling

230

231

```python

232

from connexion.exceptions import BadRequestProblem, NotFoundProblem

233

234

def get_user(user_id: int):

235

"""Get user by ID with proper error handling"""

236

237

# Validate input

238

if user_id <= 0:

239

raise BadRequestProblem(

240

detail="User ID must be a positive integer",

241

user_id=user_id

242

)

243

244

# Look up user

245

user = find_user_by_id(user_id)

246

if not user:

247

raise NotFoundProblem(

248

detail=f"User with ID {user_id} not found",

249

user_id=user_id

250

)

251

252

return user.to_dict()

253

```

254

255

### Custom Problem Types

256

257

```python

258

from connexion.exceptions import ProblemException

259

260

class RateLimitExceededProblem(ProblemException):

261

"""429 Too Many Requests - Rate limit exceeded"""

262

def __init__(self, limit: int, window: int, **kwargs):

263

super().__init__(

264

status=429,

265

title="Rate Limit Exceeded",

266

detail=f"Rate limit of {limit} requests per {window} seconds exceeded",

267

type="https://api.example.com/problems/rate-limit-exceeded",

268

limit=limit,

269

window=window,

270

**kwargs

271

)

272

273

# Usage

274

def api_endpoint():

275

if is_rate_limited(request.remote_addr):

276

raise RateLimitExceededProblem(

277

limit=100,

278

window=3600,

279

retry_after=calculate_retry_after()

280

)

281

282

# Process request...

283

return {"result": "success"}

284

```

285

286

### Validation Error Handling

287

288

```python

289

from connexion.exceptions import ValidationError, TypeValidationError

290

291

def create_user():

292

"""Create user with comprehensive validation"""

293

data = request.json

294

295

# Required field validation

296

if not data.get('email'):

297

raise ValidationError(

298

detail="Email is required",

299

field="email"

300

)

301

302

# Format validation

303

if not is_valid_email(data['email']):

304

raise ValidationError(

305

detail="Invalid email format",

306

field="email",

307

value=data['email']

308

)

309

310

# Type validation

311

age = data.get('age')

312

if age is not None and not isinstance(age, int):

313

raise TypeValidationError(

314

field="age",

315

expected_type="integer",

316

actual_type=type(age).__name__

317

)

318

319

# Business rule validation

320

if age is not None and age < 0:

321

raise ValidationError(

322

detail="Age cannot be negative",

323

field="age",

324

value=age

325

)

326

327

# Create user...

328

user = create_user_record(data)

329

return user.to_dict(), 201

330

```

331

332

### Global Error Handler

333

334

```python

335

from connexion.exceptions import ProblemException, ConnexionException

336

337

def global_error_handler(exception):

338

"""Global error handler for all exceptions"""

339

340

# Handle Connexion problem exceptions

341

if isinstance(exception, ProblemException):

342

return exception.to_problem(), exception.status

343

344

# Handle other Connexion exceptions

345

if isinstance(exception, ConnexionException):

346

return {

347

"error": "Internal error",

348

"type": type(exception).__name__,

349

"detail": str(exception)

350

}, 500

351

352

# Handle unexpected exceptions

353

import traceback

354

logger.error(f"Unexpected error: {exception}", exc_info=True)

355

356

return {

357

"error": "Internal server error",

358

"type": "UnexpectedError"

359

}, 500

360

361

# Register global error handler

362

app.add_error_handler(Exception, global_error_handler)

363

```

364

365

### Context-Aware Error Handling

366

367

```python

368

from connexion.exceptions import ForbiddenProblem, UnauthorizedProblem

369

370

def delete_user(user_id: int):

371

"""Delete user with authorization checks"""

372

373

# Check authentication

374

current_user = request.context.get('user')

375

if not current_user:

376

raise UnauthorizedProblem(

377

detail="Authentication required to delete users"

378

)

379

380

# Check authorization

381

if current_user['user_id'] != user_id and 'admin' not in current_user['roles']:

382

raise ForbiddenProblem(

383

detail="You can only delete your own account",

384

current_user_id=current_user['user_id'],

385

target_user_id=user_id

386

)

387

388

# Check if user exists

389

if not user_exists(user_id):

390

raise NotFoundProblem(

391

detail=f"User {user_id} not found"

392

)

393

394

# Perform deletion

395

delete_user_record(user_id)

396

return NoContent, 204

397

```

398

399

### Exception with Retry Information

400

401

```python

402

from connexion.exceptions import ServiceUnavailableProblem

403

import random

404

405

def external_service_call():

406

"""Call external service with retry information on failure"""

407

408

try:

409

result = call_external_api()

410

return result

411

except ExternalServiceError as e:

412

# Calculate retry delay

413

retry_after = random.randint(30, 120) # 30-120 seconds

414

415

raise ServiceUnavailableProblem(

416

detail="External service temporarily unavailable",

417

type="https://api.example.com/problems/external-service-unavailable",

418

service="payment-processor",

419

retry_after=retry_after,

420

error_code=e.code

421

)

422

```

423

424

### Detailed Validation Errors

425

426

```python

427

from connexion.exceptions import UnprocessableEntityProblem

428

429

def bulk_create_users():

430

"""Create multiple users with detailed error reporting"""

431

users_data = request.json.get('users', [])

432

errors = []

433

434

for i, user_data in enumerate(users_data):

435

user_errors = validate_user_data(user_data)

436

if user_errors:

437

errors.append({

438

'index': i,

439

'errors': user_errors

440

})

441

442

if errors:

443

raise UnprocessableEntityProblem(

444

detail="Validation failed for one or more users",

445

type="https://api.example.com/problems/bulk-validation-error",

446

invalid_users=errors,

447

total_users=len(users_data),

448

failed_count=len(errors)

449

)

450

451

# Create all users...

452

created_users = [create_user_record(data) for data in users_data]

453

return {"created_users": len(created_users)}, 201

454

455

def validate_user_data(data):

456

"""Validate individual user data and return list of errors"""

457

errors = []

458

459

if not data.get('email'):

460

errors.append({'field': 'email', 'message': 'Email is required'})

461

elif not is_valid_email(data['email']):

462

errors.append({'field': 'email', 'message': 'Invalid email format'})

463

464

if 'age' in data and (not isinstance(data['age'], int) or data['age'] < 0):

465

errors.append({'field': 'age', 'message': 'Age must be a non-negative integer'})

466

467

return errors

468

```

469

470

### Exception Chaining

471

472

```python

473

from connexion.exceptions import InternalServerErrorProblem

474

475

def complex_operation():

476

"""Complex operation with exception chaining"""

477

478

try:

479

# Step 1: Database operation

480

result1 = database_operation()

481

482

# Step 2: External API call

483

result2 = external_api_call(result1)

484

485

# Step 3: Final processing

486

return process_results(result1, result2)

487

488

except DatabaseError as e:

489

raise InternalServerErrorProblem(

490

detail="Database operation failed",

491

type="https://api.example.com/problems/database-error",

492

operation="complex_operation",

493

step="database_operation",

494

original_error=str(e)

495

) from e

496

497

except ExternalAPIError as e:

498

raise InternalServerErrorProblem(

499

detail="External service call failed",

500

type="https://api.example.com/problems/external-api-error",

501

operation="complex_operation",

502

step="external_api_call",

503

service_url=e.url,

504

original_error=str(e)

505

) from e

506

```