or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-operations.mdbatch-operations.mdentity-data-types.mderror-handling.mdindex.mdsecurity-access-control.mdservice-management.mdtable-operations.md

error-handling.mddocs/

0

# Error Handling

1

2

Comprehensive exception handling with specific error codes, transaction failure management, and detailed error information for robust Azure Tables application development.

3

4

## Capabilities

5

6

### Exception Types

7

8

Azure Tables library provides specific exception types for different error scenarios with detailed error information.

9

10

```python { .api }

11

class TableTransactionError(HttpResponseError):

12

"""

13

Exception raised when a batch transaction operation fails.

14

15

Inherits from HttpResponseError and contains detailed information

16

about which operation failed and the specific error that occurred.

17

"""

18

19

def __init__(self, **kwargs: Any) -> None:

20

"""

21

Initialize transaction error.

22

23

Parameters:

24

- **kwargs: Keyword arguments passed to HttpResponseError base class

25

including message, response, and other error details

26

"""

27

28

@property

29

def index(self) -> int:

30

"""

31

Index of the failed operation in the transaction (0-based).

32

33

Automatically extracted from error message or defaults to 0

34

if index cannot be determined.

35

"""

36

37

@property

38

def error_code(self) -> TableErrorCode:

39

"""Specific error code for the failure."""

40

41

@property

42

def message(self) -> str:

43

"""Human-readable error message."""

44

45

@property

46

def additional_info(self) -> Mapping[str, Any]:

47

"""Additional error information and context."""

48

49

class RequestTooLargeError(TableTransactionError):

50

"""

51

Exception for HTTP 413 - Request Entity Too Large errors.

52

53

Raised when the request payload exceeds service limits.

54

Inherits all properties and methods from TableTransactionError.

55

"""

56

```

57

58

#### Usage Example

59

60

```python

61

from azure.data.tables import TableClient, TableTransactionError, RequestTooLargeError

62

63

table_client = TableClient.from_connection_string(conn_str, "orders")

64

65

# Handle transaction errors

66

operations = [

67

("create", {"PartitionKey": "batch", "RowKey": "001", "Name": "Order 1"}),

68

("create", {"PartitionKey": "batch", "RowKey": "002", "Name": "Order 2"}),

69

("update", {"PartitionKey": "batch", "RowKey": "999", "Name": "Non-existent"})

70

]

71

72

try:

73

results = table_client.submit_transaction(operations)

74

except TableTransactionError as e:

75

print(f"Transaction failed at operation {e.index}")

76

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

77

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

78

79

if e.additional_info:

80

print(f"Additional details: {e.additional_info}")

81

82

# Handle specific error

83

if e.error_code == TableErrorCode.RESOURCE_NOT_FOUND:

84

print("The entity being updated doesn't exist")

85

86

# Handle request size errors

87

try:

88

large_entity = {"PartitionKey": "big", "RowKey": "001"}

89

# Add lots of data that exceeds 1MB limit

90

large_entity["BigData"] = "x" * (1024 * 1024 + 1)

91

table_client.create_entity(large_entity)

92

except RequestTooLargeError as e:

93

print(f"Entity too large: {e.message}")

94

# Split data or reduce entity size

95

```

96

97

### Error Code System

98

99

Comprehensive enumeration of error codes for different failure scenarios.

100

101

```python { .api }

102

class TableErrorCode(str, Enum):

103

"""

104

Comprehensive error codes for Azure Tables service operations.

105

106

Covers authentication, authorization, resource management,

107

entity operations, validation, condition checking, and service errors.

108

"""

109

110

# Account and Authentication Errors

111

ACCOUNT_ALREADY_EXISTS = "AccountAlreadyExists"

112

ACCOUNT_BEING_CREATED = "AccountBeingCreated"

113

ACCOUNT_IS_DISABLED = "AccountIsDisabled"

114

AUTHENTICATION_FAILED = "AuthenticationFailed"

115

AUTHORIZATION_FAILURE = "AuthorizationFailure"

116

NO_AUTHENTICATION_INFORMATION = "NoAuthenticationInformation"

117

INVALID_AUTHENTICATION_INFO = "InvalidAuthenticationInfo"

118

INSUFFICIENT_ACCOUNT_PERMISSIONS = "InsufficientAccountPermissions"

119

120

# Condition and Concurrency Errors

121

CONDITION_HEADERS_NOT_SUPPORTED = "ConditionHeadersNotSupported"

122

CONDITION_NOT_MET = "ConditionNotMet"

123

UPDATE_CONDITION_NOT_SATISFIED = "UpdateConditionNotSatisfied"

124

MULTIPLE_CONDITION_HEADERS_NOT_SUPPORTED = "MultipleConditionHeadersNotSupported"

125

126

# Resource Management Errors

127

RESOURCE_NOT_FOUND = "ResourceNotFound"

128

RESOURCE_ALREADY_EXISTS = "ResourceAlreadyExists"

129

RESOURCE_TYPE_MISMATCH = "ResourceTypeMismatch"

130

TABLE_NOT_FOUND = "TableNotFound"

131

TABLE_ALREADY_EXISTS = "TableAlreadyExists"

132

TABLE_BEING_DELETED = "TableBeingDeleted"

133

134

# Entity Operation Errors

135

ENTITY_NOT_FOUND = "EntityNotFound"

136

ENTITY_ALREADY_EXISTS = "EntityAlreadyExists"

137

ENTITY_TOO_LARGE = "EntityTooLarge"

138

139

# Property and Data Validation Errors

140

DUPLICATE_PROPERTIES_SPECIFIED = "DuplicatePropertiesSpecified"

141

PROPERTIES_NEED_VALUE = "PropertiesNeedValue"

142

PROPERTY_NAME_INVALID = "PropertyNameInvalid"

143

PROPERTY_NAME_TOO_LONG = "PropertyNameTooLong"

144

PROPERTY_VALUE_TOO_LARGE = "PropertyValueTooLarge"

145

TOO_MANY_PROPERTIES = "TooManyProperties"

146

INVALID_VALUE_TYPE = "InvalidValueType"

147

INVALID_DUPLICATE_ROW = "InvalidDuplicateRow"

148

149

# Request Validation Errors

150

INVALID_INPUT = "InvalidInput"

151

INVALID_RESOURCE_NAME = "InvalidResourceName"

152

INVALID_HEADER_VALUE = "InvalidHeaderValue"

153

INVALID_HTTP_VERB = "InvalidHttpVerb"

154

INVALID_MD5 = "InvalidMd5"

155

INVALID_METADATA = "InvalidMetadata"

156

INVALID_QUERY_PARAMETER_VALUE = "InvalidQueryParameterValue"

157

INVALID_RANGE = "InvalidRange"

158

INVALID_URI = "InvalidUri"

159

INVALID_XML_DOCUMENT = "InvalidXmlDocument"

160

INVALID_XML_NODE_VALUE = "InvalidXmlNodeValue"

161

OUT_OF_RANGE_INPUT = "OutOfRangeInput"

162

OUT_OF_RANGE_QUERY_PARAMETER_VALUE = "OutOfRangeQueryParameterValue"

163

164

# Request Format and Size Errors

165

REQUEST_BODY_TOO_LARGE = "RequestBodyTooLarge"

166

REQUEST_URL_FAILED_TO_PARSE = "RequestUrlFailedToParse"

167

METADATA_TOO_LARGE = "MetadataTooLarge"

168

EMPTY_METADATA_KEY = "EmptyMetadataKey"

169

MD5_MISMATCH = "Md5Mismatch"

170

171

# Missing Required Elements

172

MISSING_CONTENT_LENGTH_HEADER = "MissingContentLengthHeader"

173

MISSING_REQUIRED_QUERY_PARAMETER = "MissingRequiredQueryParameter"

174

MISSING_REQUIRED_HEADER = "MissingRequiredHeader"

175

MISSING_REQUIRED_XML_NODE = "MissingRequiredXmlNode"

176

HOST_INFORMATION_NOT_PRESENT = "HostInformationNotPresent"

177

178

# Service and Operation Errors

179

INTERNAL_ERROR = "InternalError"

180

OPERATION_TIMED_OUT = "OperationTimedOut"

181

SERVER_BUSY = "ServerBusy"

182

METHOD_NOT_ALLOWED = "MethodNotAllowed"

183

NOT_IMPLEMENTED = "NotImplemented"

184

185

# Unsupported Operations

186

UNSUPPORTED_HEADER = "UnsupportedHeader"

187

UNSUPPORTED_XML_NODE = "UnsupportedXmlNode"

188

UNSUPPORTED_QUERY_PARAMETER = "UnsupportedQueryParameter"

189

UNSUPPORTED_HTTP_VERB = "UnsupportedHttpVerb"

190

JSON_FORMAT_NOT_SUPPORTED = "JsonFormatNotSupported"

191

192

# X-Method Related Errors

193

X_METHOD_INCORRECT_COUNT = "XMethodIncorrectCount"

194

X_METHOD_INCORRECT_VALUE = "XMethodIncorrectValue"

195

X_METHOD_NOT_USING_POST = "XMethodNotUsingPost"

196

```

197

198

#### Usage Example

199

200

```python

201

from azure.data.tables import TableClient, TableErrorCode

202

from azure.core.exceptions import ResourceNotFoundError, ResourceExistsError

203

204

table_client = TableClient.from_connection_string(conn_str, "products")

205

206

# Handle specific error scenarios

207

def safe_entity_operations():

208

try:

209

# Try to get entity

210

entity = table_client.get_entity("electronics", "laptop001")

211

return entity

212

213

except ResourceNotFoundError as e:

214

if hasattr(e, 'error_code') and e.error_code == TableErrorCode.ENTITY_NOT_FOUND:

215

print("Entity doesn't exist, creating new one")

216

new_entity = {

217

"PartitionKey": "electronics",

218

"RowKey": "laptop001",

219

"Name": "Default Laptop",

220

"Price": 999.99

221

}

222

return table_client.create_entity(new_entity)

223

else:

224

print(f"Table or other resource not found: {e}")

225

raise

226

227

except ResourceExistsError as e:

228

if hasattr(e, 'error_code') and e.error_code == TableErrorCode.ENTITY_ALREADY_EXISTS:

229

print("Entity already exists, updating instead")

230

# Handle duplicate creation attempt

231

return table_client.update_entity(entity)

232

else:

233

raise

234

235

# Check for authentication issues

236

def handle_auth_errors():

237

try:

238

tables = list(table_client.list_entities())

239

240

except Exception as e:

241

if hasattr(e, 'error_code'):

242

if e.error_code == TableErrorCode.AUTHENTICATION_FAILED:

243

print("Check your account key or connection string")

244

elif e.error_code == TableErrorCode.AUTHORIZATION_FAILURE:

245

print("Check your permissions or SAS token scope")

246

elif e.error_code == TableErrorCode.INSUFFICIENT_ACCOUNT_PERMISSIONS:

247

print("Account needs additional permissions for this operation")

248

raise

249

```

250

251

### Common Error Scenarios

252

253

Typical error scenarios and recommended handling strategies.

254

255

#### Authentication and Authorization Errors

256

257

```python

258

from azure.data.tables import TableServiceClient

259

from azure.core.exceptions import ClientAuthenticationError

260

261

def handle_auth_scenarios():

262

"""Handle common authentication scenarios."""

263

264

try:

265

service_client = TableServiceClient.from_connection_string(

266

"DefaultEndpointsProtocol=https;AccountName=test;AccountKey=invalid"

267

)

268

tables = list(service_client.list_tables())

269

270

except ClientAuthenticationError as e:

271

print("Authentication failed:")

272

273

if "invalid account key" in str(e).lower():

274

print("- Check your account key in the connection string")

275

elif "account not found" in str(e).lower():

276

print("- Verify the account name is correct")

277

elif "signature did not match" in str(e).lower():

278

print("- Account key may be incorrect or rotated")

279

280

# Suggested recovery actions

281

print("Recovery suggestions:")

282

print("1. Verify connection string in Azure portal")

283

print("2. Check if account keys were recently rotated")

284

print("3. Ensure account name and key are correctly configured")

285

```

286

287

#### Resource Management Errors

288

289

```python

290

from azure.data.tables import TableServiceClient

291

from azure.core.exceptions import ResourceNotFoundError, ResourceExistsError

292

293

def handle_resource_errors():

294

"""Handle table and resource management errors."""

295

296

service_client = TableServiceClient.from_connection_string(conn_str)

297

298

# Safe table creation

299

def create_table_safely(table_name: str):

300

try:

301

table_client = service_client.create_table(table_name)

302

print(f"Created table: {table_name}")

303

return table_client

304

305

except ResourceExistsError:

306

print(f"Table {table_name} already exists, getting existing client")

307

return service_client.get_table_client(table_name)

308

309

# Safe table deletion

310

def delete_table_safely(table_name: str):

311

try:

312

service_client.delete_table(table_name)

313

print(f"Deleted table: {table_name}")

314

315

except ResourceNotFoundError:

316

print(f"Table {table_name} doesn't exist, nothing to delete")

317

318

# Table operations with retry

319

def robust_table_operation(table_name: str):

320

max_retries = 3

321

for attempt in range(max_retries):

322

try:

323

table_client = service_client.get_table_client(table_name)

324

entities = list(table_client.list_entities())

325

return entities

326

327

except ResourceNotFoundError:

328

if attempt < max_retries - 1:

329

print(f"Table not found, creating... (attempt {attempt + 1})")

330

create_table_safely(table_name)

331

else:

332

raise

333

```

334

335

#### Entity Operation Errors

336

337

```python

338

from azure.data.tables import TableClient, UpdateMode

339

from azure.core.exceptions import ResourceNotFoundError, ResourceExistsError, ResourceModifiedError

340

341

def handle_entity_errors():

342

"""Handle entity-specific error scenarios."""

343

344

table_client = TableClient.from_connection_string(conn_str, "customers")

345

346

# Safe entity retrieval

347

def get_entity_safely(partition_key: str, row_key: str):

348

try:

349

return table_client.get_entity(partition_key, row_key)

350

except ResourceNotFoundError:

351

print(f"Entity ({partition_key}, {row_key}) not found")

352

return None

353

354

# Robust entity creation

355

def create_or_update_entity(entity_data):

356

try:

357

# Try creating first

358

result = table_client.create_entity(entity_data)

359

print("Entity created successfully")

360

return result

361

362

except ResourceExistsError:

363

print("Entity exists, updating instead")

364

try:

365

return table_client.update_entity(entity_data, mode=UpdateMode.REPLACE)

366

except ResourceNotFoundError:

367

# Race condition: entity was deleted between create failure and update

368

print("Entity disappeared, retrying create")

369

return table_client.create_entity(entity_data)

370

371

# Optimistic concurrency handling

372

def update_with_concurrency_check(partition_key: str, row_key: str, updates):

373

max_retries = 3

374

375

for attempt in range(max_retries):

376

try:

377

# Get current entity

378

entity = table_client.get_entity(partition_key, row_key)

379

380

# Apply updates

381

for key, value in updates.items():

382

entity[key] = value

383

384

# Update with concurrency check

385

return table_client.update_entity(

386

entity,

387

etag=entity.metadata['etag'],

388

match_condition=MatchConditions.IfNotModified

389

)

390

391

except ResourceModifiedError:

392

if attempt < max_retries - 1:

393

print(f"Concurrency conflict, retrying... (attempt {attempt + 1})")

394

continue

395

else:

396

print("Max retries exceeded, giving up")

397

raise

398

except ResourceNotFoundError:

399

print("Entity was deleted by another process")

400

raise

401

```

402

403

#### Batch Transaction Error Handling

404

405

```python

406

from azure.data.tables import TableClient, TableTransactionError

407

408

def handle_batch_errors():

409

"""Handle batch transaction error scenarios."""

410

411

table_client = TableClient.from_connection_string(conn_str, "orders")

412

413

def robust_batch_operation(operations):

414

"""Execute batch with detailed error handling."""

415

416

try:

417

results = table_client.submit_transaction(operations)

418

print(f"Batch completed successfully: {len(results)} operations")

419

return results

420

421

except TableTransactionError as e:

422

print(f"Batch failed at operation {e.index}")

423

failed_operation = operations[e.index]

424

425

# Analyze the failed operation

426

operation_type, entity_data = failed_operation[:2]

427

print(f"Failed operation: {operation_type}")

428

print(f"Entity: PK={entity_data.get('PartitionKey')}, RK={entity_data.get('RowKey')}")

429

print(f"Error: {e.error_code} - {e.message}")

430

431

# Handle specific error types

432

if e.error_code == TableErrorCode.ENTITY_ALREADY_EXISTS:

433

print("Consider using upsert instead of create")

434

435

elif e.error_code == TableErrorCode.ENTITY_NOT_FOUND:

436

print("Entity doesn't exist for update/delete operation")

437

438

elif e.error_code == TableErrorCode.CONDITION_NOT_MET:

439

print("Concurrency condition failed, entity was modified")

440

441

# Option: Execute operations individually for partial success

442

return execute_operations_individually(operations, e.index)

443

444

def execute_operations_individually(operations, failed_index):

445

"""Execute operations one by one, skipping the failed one."""

446

447

results = []

448

for i, operation in enumerate(operations):

449

if i == failed_index:

450

print(f"Skipping failed operation {i}")

451

results.append(None)

452

continue

453

454

try:

455

operation_type, entity_data = operation[:2]

456

457

if operation_type == "create":

458

result = table_client.create_entity(entity_data)

459

elif operation_type == "update":

460

result = table_client.update_entity(entity_data)

461

elif operation_type == "upsert":

462

result = table_client.upsert_entity(entity_data)

463

elif operation_type == "delete":

464

table_client.delete_entity(entity_data)

465

result = {"status": "deleted"}

466

467

results.append(result)

468

print(f"Operation {i} completed individually")

469

470

except Exception as individual_error:

471

print(f"Operation {i} also failed individually: {individual_error}")

472

results.append(None)

473

474

return results

475

```

476

477

### Error Recovery Patterns

478

479

Common patterns for recovering from various error conditions.

480

481

#### Retry with Exponential Backoff

482

483

```python

484

import time

485

import random

486

from azure.core.exceptions import ServiceRequestError

487

488

def retry_with_backoff(func, max_retries=3, base_delay=1.0):

489

"""Execute function with exponential backoff retry."""

490

491

for attempt in range(max_retries):

492

try:

493

return func()

494

495

except ServiceRequestError as e:

496

if attempt == max_retries - 1:

497

raise # Re-raise on final attempt

498

499

# Calculate delay with jitter

500

delay = base_delay * (2 ** attempt) + random.uniform(0, 1)

501

print(f"Attempt {attempt + 1} failed, retrying in {delay:.2f}s")

502

time.sleep(delay)

503

504

# Usage

505

def unreliable_operation():

506

return table_client.create_entity(entity_data)

507

508

result = retry_with_backoff(unreliable_operation)

509

```

510

511

#### Circuit Breaker Pattern

512

513

```python

514

from datetime import datetime, timedelta

515

516

class CircuitBreaker:

517

"""Circuit breaker for failing operations."""

518

519

def __init__(self, failure_threshold=5, timeout=60):

520

self.failure_threshold = failure_threshold

521

self.timeout = timeout

522

self.failure_count = 0

523

self.last_failure_time = None

524

self.state = "CLOSED" # CLOSED, OPEN, HALF_OPEN

525

526

def call(self, func):

527

if self.state == "OPEN":

528

if datetime.now() - self.last_failure_time > timedelta(seconds=self.timeout):

529

self.state = "HALF_OPEN"

530

else:

531

raise Exception("Circuit breaker is OPEN")

532

533

try:

534

result = func()

535

self.on_success()

536

return result

537

except Exception as e:

538

self.on_failure()

539

raise

540

541

def on_success(self):

542

self.failure_count = 0

543

self.state = "CLOSED"

544

545

def on_failure(self):

546

self.failure_count += 1

547

self.last_failure_time = datetime.now()

548

549

if self.failure_count >= self.failure_threshold:

550

self.state = "OPEN"

551

552

# Usage

553

circuit_breaker = CircuitBreaker()

554

555

def protected_operation():

556

return circuit_breaker.call(lambda: table_client.list_entities())

557

```