or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

anypath.mdazure-integration.mdclient-management.mdcloud-operations.mdconfiguration.mdcore-operations.mddirectory-operations.mdexceptions.mdfile-io.mdgcs-integration.mdhttp-support.mdindex.mdpatching.mds3-integration.md

exceptions.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy for precise error handling across different cloud providers and operation types. CloudPathLib provides specific exceptions for common cloud storage scenarios, enabling robust error handling and debugging.

3

4

## Capabilities

5

6

### Exception Hierarchy

7

8

CloudPathLib defines a comprehensive exception hierarchy for precise error handling.

9

10

```python { .api }

11

class CloudPathException(Exception):

12

"""Base exception for all CloudPathLib errors."""

13

14

class AnyPathTypeError(CloudPathException):

15

"""Raised when AnyPath receives invalid input type."""

16

17

class ClientMismatchError(CloudPathException):

18

"""Raised when wrong client type is used for a path."""

19

20

class CloudPathFileExistsError(CloudPathException, FileExistsError):

21

"""Raised when attempting to create a file that already exists."""

22

23

class CloudPathFileNotFoundError(CloudPathException, FileNotFoundError):

24

"""Raised when attempting to access a file that does not exist."""

25

26

class CloudPathIsADirectoryError(CloudPathException, IsADirectoryError):

27

"""Raised when file operation is attempted on a directory."""

28

29

class CloudPathNotADirectoryError(CloudPathException, NotADirectoryError):

30

"""Raised when directory operation is attempted on a file."""

31

32

class CloudPathNotExistsError(CloudPathException):

33

"""Raised when attempting to access a path that does not exist."""

34

35

class CloudPathNotImplementedError(CloudPathException, NotImplementedError):

36

"""Raised when an operation is not supported by the cloud provider."""

37

38

class DirectoryNotEmptyError(CloudPathException):

39

"""Raised when attempting to remove a non-empty directory."""

40

41

class IncompleteImplementationError(CloudPathException):

42

"""Raised when cloud implementation is missing required components."""

43

44

class InvalidPrefixError(CloudPathException):

45

"""Raised when an invalid cloud path prefix is used."""

46

47

class InvalidConfigurationException(CloudPathException):

48

"""Raised when client configuration is invalid."""

49

50

class MissingCredentialsError(CloudPathException):

51

"""Raised when required authentication credentials are missing."""

52

53

class MissingDependenciesError(CloudPathException):

54

"""Raised when required cloud provider dependencies are not installed."""

55

56

class NoStatError(CloudPathException):

57

"""Raised when file statistics cannot be retrieved."""

58

59

class OverwriteDirtyFileError(CloudPathException):

60

"""Raised when local cached file has been modified and conflicts with cloud version."""

61

62

class OverwriteNewerCloudError(CloudPathException):

63

"""Raised when cloud file is newer than local cached version."""

64

65

class OverwriteNewerLocalError(CloudPathException):

66

"""Raised when local cached file is newer than cloud version."""

67

68

class InvalidGlobArgumentsError(CloudPathException):

69

"""Raised when invalid arguments are passed to glob operations."""

70

```

71

72

## Usage Examples

73

74

### Basic Exception Handling

75

76

```python

77

from cloudpathlib import (

78

CloudPath,

79

CloudPathFileNotFoundError,

80

MissingCredentialsError,

81

InvalidPrefixError

82

)

83

84

def safe_read_file(path_str):

85

"""Safely read a cloud file with error handling."""

86

try:

87

path = CloudPath(path_str)

88

return path.read_text()

89

90

except CloudPathFileNotFoundError:

91

print(f"File not found: {path_str}")

92

return None

93

94

except MissingCredentialsError:

95

print("Authentication credentials not configured")

96

return None

97

98

except InvalidPrefixError:

99

print(f"Invalid cloud path prefix: {path_str}")

100

return None

101

102

except CloudPathException as e:

103

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

104

return None

105

106

# Usage

107

content = safe_read_file("s3://my-bucket/file.txt")

108

if content:

109

print("File read successfully")

110

```

111

112

### Provider-Specific Error Handling

113

114

```python

115

from cloudpathlib import CloudPath

116

import boto3.exceptions

117

import google.api_core.exceptions

118

import azure.core.exceptions

119

120

def robust_cloud_operation(path_str):

121

"""Handle errors from different cloud providers."""

122

try:

123

path = CloudPath(path_str)

124

return path.read_text()

125

126

# CloudPathLib-specific exceptions

127

except CloudPathFileNotFoundError:

128

print("File not found in cloud storage")

129

except MissingCredentialsError:

130

print("Cloud credentials not configured")

131

132

# AWS-specific exceptions

133

except boto3.exceptions.Boto3Error as e:

134

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

135

except boto3.exceptions.NoCredentialsError:

136

print("AWS credentials not found")

137

138

# Google Cloud-specific exceptions

139

except google.api_core.exceptions.GoogleAPIError as e:

140

print(f"Google Cloud error: {e}")

141

except google.api_core.exceptions.PermissionDenied:

142

print("Google Cloud permission denied")

143

144

# Azure-specific exceptions

145

except azure.core.exceptions.AzureError as e:

146

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

147

except azure.core.exceptions.ClientAuthenticationError:

148

print("Azure authentication failed")

149

150

# Generic exceptions

151

except PermissionError:

152

print("Permission denied")

153

except Exception as e:

154

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

155

156

return None

157

```

158

159

### File Operation Error Handling

160

161

```python

162

from cloudpathlib import (

163

CloudPath,

164

CloudPathFileExistsError,

165

CloudPathIsADirectoryError,

166

DirectoryNotEmptyError

167

)

168

169

def safe_file_operations():

170

"""Demonstrate error handling for file operations."""

171

172

# Safe file creation

173

def create_file_safe(path_str, content):

174

try:

175

path = CloudPath(path_str)

176

177

# Check if file already exists

178

if path.exists():

179

response = input(f"File {path} exists. Overwrite? (y/n): ")

180

if response.lower() != 'y':

181

return False

182

183

path.write_text(content)

184

return True

185

186

except CloudPathIsADirectoryError:

187

print(f"Error: {path_str} is a directory, not a file")

188

return False

189

except PermissionError:

190

print(f"Error: No permission to write to {path_str}")

191

return False

192

193

# Safe directory removal

194

def remove_directory_safe(path_str):

195

try:

196

path = CloudPath(path_str)

197

path.rmdir()

198

return True

199

200

except CloudPathNotADirectoryError:

201

print(f"Error: {path_str} is not a directory")

202

return False

203

except DirectoryNotEmptyError:

204

print(f"Error: Directory {path_str} is not empty")

205

# Offer to remove recursively

206

response = input("Remove recursively? (y/n): ")

207

if response.lower() == 'y':

208

path.rmtree()

209

return True

210

return False

211

except CloudPathFileNotFoundError:

212

print(f"Directory {path_str} does not exist")

213

return False

214

215

# Usage examples

216

create_file_safe("s3://bucket/file.txt", "Hello, world!")

217

remove_directory_safe("s3://bucket/empty-dir/")

218

219

safe_file_operations()

220

```

221

222

### Retry Logic with Exception Handling

223

224

```python

225

import time

226

import random

227

from cloudpathlib import CloudPath, CloudPathException

228

229

def retry_cloud_operation(func, max_retries=3, backoff_factor=1.0):

230

"""Retry cloud operations with exponential backoff."""

231

232

for attempt in range(max_retries):

233

try:

234

return func()

235

236

except (CloudPathFileNotFoundError, CloudPathNotExistsError):

237

# Don't retry for missing files

238

raise

239

240

except MissingCredentialsError:

241

# Don't retry for credential issues

242

raise

243

244

except CloudPathException as e:

245

if attempt == max_retries - 1:

246

# Last attempt, re-raise the exception

247

raise

248

249

# Calculate backoff time

250

backoff_time = backoff_factor * (2 ** attempt) + random.uniform(0, 1)

251

print(f"Attempt {attempt + 1} failed: {e}")

252

print(f"Retrying in {backoff_time:.2f} seconds...")

253

time.sleep(backoff_time)

254

255

except Exception as e:

256

# For non-CloudPath exceptions, only retry once

257

if attempt == 0:

258

print(f"Unexpected error: {e}, retrying once...")

259

time.sleep(1)

260

else:

261

raise

262

263

# Usage

264

def upload_file_with_retry():

265

def upload_operation():

266

path = CloudPath("s3://unreliable-bucket/file.txt")

267

path.write_text("Important data")

268

return path

269

270

try:

271

result = retry_cloud_operation(upload_operation, max_retries=3)

272

print(f"Upload successful: {result}")

273

except Exception as e:

274

print(f"Upload failed after retries: {e}")

275

276

upload_file_with_retry()

277

```

278

279

### Configuration Error Handling

280

281

```python

282

from cloudpathlib import (

283

S3Client,

284

GSClient,

285

AzureBlobClient,

286

InvalidConfigurationException,

287

MissingDependenciesError

288

)

289

290

def configure_client_safe(provider, **config):

291

"""Safely configure cloud client with error handling."""

292

293

try:

294

if provider == "s3":

295

return S3Client(**config)

296

elif provider == "gs":

297

return GSClient(**config)

298

elif provider == "azure":

299

return AzureBlobClient(**config)

300

else:

301

raise ValueError(f"Unknown provider: {provider}")

302

303

except MissingDependenciesError as e:

304

print(f"Missing dependencies for {provider}: {e}")

305

print(f"Install with: pip install cloudpathlib[{provider}]")

306

return None

307

308

except InvalidConfigurationException as e:

309

print(f"Invalid configuration for {provider}: {e}")

310

return None

311

312

except Exception as e:

313

print(f"Unexpected error configuring {provider} client: {e}")

314

return None

315

316

# Usage

317

configs = {

318

"s3": {"aws_access_key_id": "key", "aws_secret_access_key": "secret"},

319

"gs": {"application_credentials": "path/to/creds.json"},

320

"azure": {"connection_string": "connection_string"}

321

}

322

323

clients = {}

324

for provider, config in configs.items():

325

client = configure_client_safe(provider, **config)

326

if client:

327

clients[provider] = client

328

print(f"{provider} client configured successfully")

329

```

330

331

### Batch Operation Error Handling

332

333

```python

334

from cloudpathlib import CloudPath, CloudPathException

335

from concurrent.futures import ThreadPoolExecutor, as_completed

336

337

def process_files_batch(file_paths, process_func):

338

"""Process multiple files with error handling."""

339

340

results = []

341

errors = []

342

343

def safe_process(path_str):

344

try:

345

path = CloudPath(path_str)

346

result = process_func(path)

347

return {"path": path_str, "result": result, "success": True}

348

349

except CloudPathFileNotFoundError:

350

return {"path": path_str, "error": "File not found", "success": False}

351

except PermissionError:

352

return {"path": path_str, "error": "Permission denied", "success": False}

353

except CloudPathException as e:

354

return {"path": path_str, "error": str(e), "success": False}

355

except Exception as e:

356

return {"path": path_str, "error": f"Unexpected: {e}", "success": False}

357

358

# Process files concurrently

359

with ThreadPoolExecutor(max_workers=5) as executor:

360

future_to_path = {

361

executor.submit(safe_process, path): path

362

for path in file_paths

363

}

364

365

for future in as_completed(future_to_path):

366

result = future.result()

367

368

if result["success"]:

369

results.append(result)

370

else:

371

errors.append(result)

372

print(f"Error processing {result['path']}: {result['error']}")

373

374

return results, errors

375

376

# Usage

377

def read_file_size(path):

378

"""Example processing function."""

379

return path.stat().st_size

380

381

file_list = [

382

"s3://bucket/file1.txt",

383

"s3://bucket/file2.txt",

384

"s3://bucket/nonexistent.txt",

385

"gs://bucket/file3.txt"

386

]

387

388

successful_results, failed_results = process_files_batch(file_list, read_file_size)

389

390

print(f"Successfully processed {len(successful_results)} files")

391

print(f"Failed to process {len(failed_results)} files")

392

```

393

394

### Custom Exception Handling

395

396

```python

397

from cloudpathlib import CloudPathException

398

399

class DataProcessingError(CloudPathException):

400

"""Custom exception for data processing errors."""

401

pass

402

403

class InvalidDataFormatError(DataProcessingError):

404

"""Raised when data format is invalid."""

405

pass

406

407

def process_data_file(path_str):

408

"""Process data file with custom exception handling."""

409

410

try:

411

path = CloudPath(path_str)

412

413

if not path.exists():

414

raise CloudPathFileNotFoundError(f"Data file not found: {path_str}")

415

416

content = path.read_text()

417

418

# Custom validation

419

if not content.strip():

420

raise InvalidDataFormatError(f"Data file is empty: {path_str}")

421

422

if not content.startswith("DATA_VERSION"):

423

raise InvalidDataFormatError(f"Invalid data format: {path_str}")

424

425

# Process data...

426

processed = content.upper()

427

428

output_path = path.with_stem(path.stem + "_processed")

429

output_path.write_text(processed)

430

431

return output_path

432

433

except InvalidDataFormatError as e:

434

print(f"Data format error: {e}")

435

raise # Re-raise custom exception

436

437

except DataProcessingError as e:

438

print(f"Data processing error: {e}")

439

raise

440

441

except CloudPathException as e:

442

print(f"Cloud storage error: {e}")

443

raise DataProcessingError(f"Failed to process {path_str}") from e

444

445

# Usage with custom exception handling

446

try:

447

result = process_data_file("s3://data-bucket/dataset.txt")

448

print(f"Processing complete: {result}")

449

450

except InvalidDataFormatError:

451

print("Fix data format and try again")

452

except DataProcessingError:

453

print("Data processing failed")

454

except Exception as e:

455

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

456

```

457

458

### Logging and Monitoring

459

460

```python

461

import logging

462

from cloudpathlib import CloudPath, CloudPathException

463

464

# Configure logging

465

logging.basicConfig(level=logging.INFO)

466

logger = logging.getLogger(__name__)

467

468

def monitored_cloud_operation(path_str, operation):

469

"""Perform cloud operation with comprehensive logging."""

470

471

logger.info(f"Starting {operation} on {path_str}")

472

473

try:

474

path = CloudPath(path_str)

475

476

if operation == "read":

477

result = path.read_text()

478

logger.info(f"Successfully read {len(result)} characters from {path_str}")

479

return result

480

481

elif operation == "exists":

482

result = path.exists()

483

logger.info(f"Existence check for {path_str}: {result}")

484

return result

485

486

elif operation == "stat":

487

result = path.stat()

488

logger.info(f"File stats for {path_str}: size={result.st_size}")

489

return result

490

491

else:

492

raise ValueError(f"Unknown operation: {operation}")

493

494

except CloudPathFileNotFoundError as e:

495

logger.warning(f"File not found during {operation}: {path_str}")

496

raise

497

498

except MissingCredentialsError as e:

499

logger.error(f"Credentials missing for {operation} on {path_str}")

500

raise

501

502

except CloudPathException as e:

503

logger.error(f"CloudPath error during {operation} on {path_str}: {e}")

504

raise

505

506

except Exception as e:

507

logger.error(f"Unexpected error during {operation} on {path_str}: {e}")

508

raise

509

510

# Usage with monitoring

511

try:

512

content = monitored_cloud_operation("s3://bucket/file.txt", "read")

513

stats = monitored_cloud_operation("s3://bucket/file.txt", "stat")

514

515

except CloudPathException as e:

516

logger.error(f"Operation failed: {e}")

517

```

518

519

### Error Recovery Patterns

520

521

```python

522

from cloudpathlib import CloudPath, CloudPathFileNotFoundError

523

524

def resilient_data_access(primary_path, backup_paths=None):

525

"""Access data with fallback to backup locations."""

526

527

backup_paths = backup_paths or []

528

all_paths = [primary_path] + backup_paths

529

530

last_exception = None

531

532

for i, path_str in enumerate(all_paths):

533

try:

534

path = CloudPath(path_str)

535

content = path.read_text()

536

537

if i > 0:

538

print(f"Successfully accessed backup path: {path_str}")

539

540

return content

541

542

except CloudPathFileNotFoundError as e:

543

last_exception = e

544

if i < len(all_paths) - 1:

545

print(f"Primary path failed, trying backup: {all_paths[i + 1]}")

546

continue

547

548

except CloudPathException as e:

549

last_exception = e

550

print(f"Error accessing {path_str}: {e}")

551

continue

552

553

# All paths failed

554

raise CloudPathFileNotFoundError(

555

f"Could not access data from any location. Last error: {last_exception}"

556

)

557

558

# Usage

559

try:

560

data = resilient_data_access(

561

primary_path="s3://primary-bucket/data.txt",

562

backup_paths=[

563

"s3://backup-bucket/data.txt",

564

"gs://backup-bucket/data.txt",

565

"/local/backup/data.txt"

566

]

567

)

568

print("Data accessed successfully")

569

570

except CloudPathException as e:

571

print(f"All data sources failed: {e}")

572

```