or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-utilities.mdconfiguration.mdcore-validation.mdexception-handling.mdindex.mdresults-output.md

exception-handling.mddocs/

0

# Exception Handling

1

2

Comprehensive exception hierarchy for different validation error scenarios, enabling precise error handling and programmatic response to validation failures.

3

4

## Capabilities

5

6

### Base Exception Classes

7

8

Core exception types that form the foundation of the STIX validator's error handling system.

9

10

```python { .api }

11

class ValidationError(Exception):

12

"""

13

Base Exception for all validator-specific exceptions.

14

15

Description:

16

This can be used directly as a generic Exception or as a base class

17

for more specific validation errors. All validator-specific exceptions

18

inherit from this class.

19

"""

20

pass

21

```

22

23

**Example Usage:**

24

25

```python

26

from stix2validator import validate_string, ValidationError

27

28

try:

29

result = validate_string('{"invalid": "json"}')

30

except ValidationError as e:

31

print(f"Validation error occurred: {e}")

32

# Handle any validator-specific error

33

except Exception as e:

34

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

35

```

36

37

### Schema-Related Exceptions

38

39

Exceptions specifically related to JSON Schema validation and schema file issues.

40

41

```python { .api }

42

class SchemaInvalidError(ValidationError):

43

"""

44

Represent an error with the JSON Schema file itself.

45

46

Description:

47

Raised when there are problems with the STIX JSON schema files

48

used for validation, such as malformed schema definitions or

49

missing schema components.

50

"""

51

pass

52

53

class SchemaError(ValidationError):

54

"""

55

Represent a JSON Schema validation error.

56

57

Parameters:

58

- error: An error returned from JSON Schema validation

59

60

Attributes:

61

- message: The JSON validation error message

62

63

Methods:

64

- as_dict(): Returns a dictionary representation

65

- __str__(): Returns string representation of the message

66

"""

67

68

def __init__(self, error):

69

pass

70

71

def as_dict(self):

72

"""Return dictionary representation of the schema error."""

73

pass

74

75

def __str__(self):

76

"""Return string representation of the error message."""

77

pass

78

```

79

80

**Example Usage:**

81

82

```python

83

from stix2validator import validate_instance, SchemaError, SchemaInvalidError

84

85

# Example STIX object with schema violations

86

invalid_stix = {

87

"type": "indicator",

88

"id": "not-a-valid-uuid", # Invalid UUID format

89

"pattern": "[file:hashes.MD5 = 'invalid']",

90

"labels": "not-a-list" # Should be a list

91

}

92

93

try:

94

result = validate_instance(invalid_stix)

95

if not result.get('valid'):

96

for error in result.get('errors', []):

97

if isinstance(error, SchemaError):

98

print(f"Schema validation error: {error.message}")

99

print(f"Error details: {error.as_dict()}")

100

101

except SchemaInvalidError as e:

102

print(f"Schema file problem: {e}")

103

# Handle issues with schema files themselves

104

105

except SchemaError as e:

106

print(f"Schema validation failed: {e}")

107

# Handle specific schema validation failures

108

```

109

110

### Pattern Validation Exceptions

111

112

Specialized exceptions for STIX pattern validation issues.

113

114

```python { .api }

115

class PatternError(schema_exceptions.ValidationError):

116

"""

117

Represent a problem with a STIX Pattern.

118

119

Parameters:

120

- msg (str, optional): Error message (default: None)

121

- instance_id (str, optional): Instance identifier (default: None)

122

123

Description:

124

Raised when STIX indicator patterns fail to validate against

125

the STIX pattern grammar or contain syntax errors.

126

"""

127

128

def __init__(self, msg=None, instance_id=None):

129

pass

130

```

131

132

**Example Usage:**

133

134

```python

135

from stix2validator import validate_string, PatternError

136

137

# STIX indicator with invalid pattern

138

invalid_pattern = '''

139

{

140

"type": "indicator",

141

"spec_version": "2.1",

142

"id": "indicator--12345678-1234-1234-1234-123456789012",

143

"created": "2023-01-01T00:00:00.000Z",

144

"modified": "2023-01-01T00:00:00.000Z",

145

"pattern": "[invalid-pattern-syntax]",

146

"labels": ["malicious-activity"]

147

}

148

'''

149

150

try:

151

result = validate_string(invalid_pattern)

152

if not result.is_valid:

153

for error in result.errors:

154

if "Pattern" in str(error):

155

print(f"Pattern validation failed: {error}")

156

157

except PatternError as e:

158

print(f"STIX pattern error: {e}")

159

# Handle pattern-specific validation failures

160

```

161

162

### File System Exceptions

163

164

Exceptions related to file I/O operations during validation.

165

166

```python { .api }

167

class NoJSONFileFoundError(OSError):

168

"""

169

Represent a problem finding the input JSON file(s).

170

171

Description:

172

Raised when specified JSON files cannot be found or accessed

173

during file-based validation operations.

174

"""

175

pass

176

```

177

178

**Example Usage:**

179

180

```python

181

from stix2validator import validate_file, NoJSONFileFoundError

182

183

files_to_validate = [

184

"existing_file.json",

185

"missing_file.json",

186

"inaccessible_file.json"

187

]

188

189

for filename in files_to_validate:

190

try:

191

result = validate_file(filename)

192

print(f"✓ {filename}: {'Valid' if result.is_valid else 'Invalid'}")

193

194

except NoJSONFileFoundError as e:

195

print(f"✗ {filename}: File not found - {e}")

196

197

except PermissionError as e:

198

print(f"✗ {filename}: Permission denied - {e}")

199

200

except ValidationError as e:

201

print(f"✗ {filename}: Validation error - {e}")

202

```

203

204

### Error Formatting Utilities

205

206

Helper functions for formatting and presenting validation errors in a user-friendly manner.

207

208

```python { .api }

209

def pretty_error(error, verbose=False):

210

"""

211

Return an error message that is easier to read and more useful.

212

213

Parameters:

214

- error: The error object to format

215

- verbose (bool): Whether to include verbose error information (default: False)

216

217

Returns:

218

str: A formatted error message that is easier to read and more useful

219

220

Description:

221

Transforms technical validation error messages into more readable

222

and actionable error descriptions. May require updating if the

223

schemas change significantly.

224

"""

225

226

def remove_u(input):

227

"""

228

Remove ugly u'' prefixes from input string.

229

230

Parameters:

231

- input (str): Input string potentially containing u'' prefixes

232

233

Returns:

234

str: String with u'' prefixes removed

235

236

Description:

237

Utility function for cleaning up string representations by removing

238

Python 2 style unicode prefixes from error messages and output.

239

"""

240

```

241

242

**Example Usage:**

243

244

```python

245

from stix2validator import validate_string

246

from stix2validator.errors import pretty_error, remove_u

247

248

# Validate STIX with errors

249

stix_with_errors = '''

250

{

251

"type": "indicator",

252

"spec_version": "2.1",

253

"id": "invalid-uuid-format",

254

"created": "not-a-timestamp",

255

"modified": "2023-01-01T00:00:00.000Z",

256

"pattern": "[file:hashes.MD5 = 'hash']",

257

"labels": ["malicious-activity"]

258

}

259

'''

260

261

result = validate_string(stix_with_errors)

262

263

if not result.is_valid:

264

for error in result.errors:

265

# Format error for better readability

266

formatted_error = pretty_error(error, verbose=True)

267

print(f"Formatted error: {formatted_error}")

268

269

# Compare with raw error

270

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

271

print("---")

272

273

# Example of remove_u utility function

274

raw_error_message = "u'invalid' does not match u'pattern'"

275

cleaned_message = remove_u(raw_error_message)

276

print(f"Raw: {raw_error_message}")

277

print(f"Cleaned: {cleaned_message}")

278

```

279

280

## Advanced Exception Handling Patterns

281

282

### Comprehensive Error Handling

283

284

```python

285

from stix2validator import (

286

validate_file, validate_string, validate_instance,

287

ValidationError, SchemaError, SchemaInvalidError,

288

NoJSONFileFoundError, PatternError

289

)

290

from stix2validator.errors import pretty_error

291

import json

292

293

def robust_stix_validation(input_data, input_type="string"):

294

"""

295

Comprehensive STIX validation with detailed error handling.

296

297

Parameters:

298

- input_data: STIX data (string, dict, or filename)

299

- input_type: Type of input ("string", "instance", "file")

300

301

Returns:

302

dict: Validation results with detailed error information

303

"""

304

result_info = {

305

"valid": False,

306

"errors": [],

307

"warnings": [],

308

"error_types": [],

309

"input_type": input_type

310

}

311

312

try:

313

# Select appropriate validation function

314

if input_type == "file":

315

result = validate_file(input_data)

316

elif input_type == "string":

317

result = validate_string(input_data)

318

elif input_type == "instance":

319

result = validate_instance(input_data)

320

else:

321

raise ValueError(f"Invalid input_type: {input_type}")

322

323

# Process results

324

result_info["valid"] = result.is_valid

325

326

if hasattr(result, 'object_results'):

327

# File validation results

328

for obj_result in result.object_results:

329

if obj_result.errors:

330

for error in obj_result.errors:

331

formatted_error = pretty_error(error, verbose=True)

332

result_info["errors"].append(formatted_error)

333

result_info["error_types"].append(type(error).__name__)

334

335

if obj_result.warnings:

336

result_info["warnings"].extend(obj_result.warnings)

337

else:

338

# Object validation results

339

if hasattr(result, 'errors') and result.errors:

340

for error in result.errors:

341

formatted_error = pretty_error(error, verbose=True)

342

result_info["errors"].append(formatted_error)

343

result_info["error_types"].append(type(error).__name__)

344

345

if hasattr(result, 'warnings') and result.warnings:

346

result_info["warnings"].extend(result.warnings)

347

348

except NoJSONFileFoundError as e:

349

result_info["errors"].append(f"File not found: {e}")

350

result_info["error_types"].append("NoJSONFileFoundError")

351

352

except SchemaInvalidError as e:

353

result_info["errors"].append(f"Schema file error: {e}")

354

result_info["error_types"].append("SchemaInvalidError")

355

356

except SchemaError as e:

357

result_info["errors"].append(f"Schema validation error: {e.message}")

358

result_info["error_types"].append("SchemaError")

359

360

except PatternError as e:

361

result_info["errors"].append(f"Pattern error: {e}")

362

result_info["error_types"].append("PatternError")

363

364

except json.JSONDecodeError as e:

365

result_info["errors"].append(f"JSON parsing error: {e}")

366

result_info["error_types"].append("JSONDecodeError")

367

368

except ValidationError as e:

369

result_info["errors"].append(f"Validation error: {e}")

370

result_info["error_types"].append("ValidationError")

371

372

except Exception as e:

373

result_info["errors"].append(f"Unexpected error: {e}")

374

result_info["error_types"].append(type(e).__name__)

375

376

return result_info

377

378

# Usage examples

379

print("=== File Validation ===")

380

file_result = robust_stix_validation("threat_data.json", "file")

381

print(f"Valid: {file_result['valid']}")

382

for error in file_result["errors"]:

383

print(f"Error: {error}")

384

385

print("\n=== String Validation ===")

386

stix_string = '{"type": "malware", "name": "BadMalware", ...}'

387

string_result = robust_stix_validation(stix_string, "string")

388

print(f"Valid: {string_result['valid']}")

389

390

print("\n=== Instance Validation ===")

391

stix_dict = {"type": "threat-actor", "name": "APT Group", "labels": ["hacker"]}

392

instance_result = robust_stix_validation(stix_dict, "instance")

393

print(f"Valid: {instance_result['valid']}")

394

```

395

396

### Error Recovery and Retry Logic

397

398

```python

399

import time

400

from stix2validator import validate_file, ValidationError, NoJSONFileFoundError

401

402

def validate_with_retry(filename, max_retries=3, retry_delay=1.0):

403

"""

404

Validate STIX file with retry logic for transient errors.

405

"""

406

for attempt in range(max_retries):

407

try:

408

result = validate_file(filename)

409

return result

410

411

except NoJSONFileFoundError:

412

# Don't retry for file not found

413

raise

414

415

except ValidationError as e:

416

if "schema" in str(e).lower() and attempt < max_retries - 1:

417

# Retry schema-related errors (might be transient)

418

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

419

time.sleep(retry_delay)

420

continue

421

else:

422

# Re-raise if max retries reached or non-retryable error

423

raise

424

425

except Exception as e:

426

if attempt < max_retries - 1:

427

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

428

time.sleep(retry_delay)

429

continue

430

else:

431

raise

432

433

raise ValidationError(f"Validation failed after {max_retries} attempts")

434

435

# Usage

436

try:

437

result = validate_with_retry("unreliable_file.json")

438

print(f"Validation successful after retries: {result.is_valid}")

439

except Exception as e:

440

print(f"Final validation failure: {e}")

441

```

442

443

### Context-Aware Error Handling

444

445

```python

446

from contextlib import contextmanager

447

from stix2validator import ValidationError

448

449

@contextmanager

450

def stix_validation_context(operation_name="STIX validation"):

451

"""

452

Context manager for enhanced error handling during STIX validation.

453

"""

454

try:

455

print(f"Starting {operation_name}...")

456

yield

457

print(f"Completed {operation_name} successfully")

458

459

except NoJSONFileFoundError as e:

460

print(f"File access error during {operation_name}: {e}")

461

raise

462

463

except ValidationError as e:

464

print(f"Validation failed during {operation_name}: {e}")

465

raise

466

467

except Exception as e:

468

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

469

raise

470

471

# Usage

472

with stix_validation_context("Threat intelligence validation"):

473

results = validate_file("threat_intel.json")

474

if not results.is_valid:

475

# Handle validation failures within context

476

handle_validation_errors(results)

477

```