or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mdcore-runtime.mderrors.mdfunctions.mdindex.mdlinking.mdmemory.mdtypes.mdutilities.mdwasi.md

errors.mddocs/

0

# Error Handling

1

2

Comprehensive error handling system including WebAssembly traps, stack traces, runtime errors, WASI exit codes, and detailed debugging information for robust WebAssembly application development and debugging.

3

4

## Capabilities

5

6

### Runtime Errors

7

8

Base exception hierarchy for WebAssembly runtime errors providing structured error reporting and debugging information for compilation, instantiation, and execution failures.

9

10

```python { .api }

11

class WasmtimeError(Exception):

12

"""Base exception for all Wasmtime-related errors"""

13

```

14

15

### WebAssembly Traps

16

17

Exception representing WebAssembly execution traps with detailed stack trace information, trap codes, and frame-by-frame execution context for debugging runtime failures.

18

19

```python { .api }

20

class Trap(Exception):

21

def __init__(self, message: str):

22

"""

23

Create a trap with the given message.

24

25

Parameters:

26

- message: Human-readable trap description

27

"""

28

29

@property

30

def message(self) -> str:

31

"""

32

Get the trap message.

33

34

Returns:

35

Human-readable trap description

36

"""

37

38

@property

39

def frames(self) -> List[Frame]:

40

"""

41

Get the stack trace frames.

42

43

Returns:

44

List of stack frames from the trap location

45

"""

46

47

@property

48

def trace(self) -> List[str]:

49

"""

50

Get the stack trace as formatted strings.

51

52

Returns:

53

List of formatted stack trace lines

54

"""

55

```

56

57

### Stack Frames

58

59

Stack frame information providing detailed execution context including function names, module names, function indices, and code offsets for precise debugging.

60

61

```python { .api }

62

class Frame:

63

@property

64

def func_name(self) -> Optional[str]:

65

"""

66

Get the function name if available.

67

68

Returns:

69

Function name from debug info, or None if not available

70

"""

71

72

@property

73

def module_name(self) -> Optional[str]:

74

"""

75

Get the module name if available.

76

77

Returns:

78

Module name from debug info, or None if not available

79

"""

80

81

@property

82

def func_index(self) -> int:

83

"""

84

Get the function index within the module.

85

86

Returns:

87

Zero-based function index

88

"""

89

90

@property

91

def module_offset(self) -> int:

92

"""

93

Get the byte offset within the module.

94

95

Returns:

96

Byte offset from start of module

97

"""

98

```

99

100

### Trap Codes

101

102

Enumeration of standard WebAssembly trap codes providing categorization of different trap conditions for programmatic error handling and recovery.

103

104

```python { .api }

105

class TrapCode:

106

STACK_OVERFLOW: 'TrapCode' # Stack overflow

107

MEMORY_OUT_OF_BOUNDS: 'TrapCode' # Memory access out of bounds

108

HEAP_MISALIGNED: 'TrapCode' # Misaligned memory access

109

TABLE_OUT_OF_BOUNDS: 'TrapCode' # Table access out of bounds

110

INDIRECT_CALL_TO_NULL: 'TrapCode' # Indirect call to null

111

BAD_SIGNATURE: 'TrapCode' # Indirect call signature mismatch

112

INTEGER_OVERFLOW: 'TrapCode' # Integer overflow

113

INTEGER_DIVISION_BY_ZERO: 'TrapCode' # Division by zero

114

BAD_CONVERSION_TO_INTEGER: 'TrapCode' # Invalid float to int conversion

115

UNREACHABLE: 'TrapCode' # Unreachable instruction executed

116

INTERRUPT: 'TrapCode' # Execution interrupted

117

```

118

119

### WASI Exit Codes

120

121

Exception representing WASI program exit with exit code information, supporting standard Unix exit code conventions and proper process termination handling.

122

123

```python { .api }

124

class ExitTrap(Exception):

125

def __init__(self, code: int):

126

"""

127

Create an exit trap with the given exit code.

128

129

Parameters:

130

- code: Exit code (0 for success, non-zero for error)

131

"""

132

133

@property

134

def code(self) -> int:

135

"""

136

Get the exit code.

137

138

Returns:

139

Exit code from the WebAssembly program

140

"""

141

```

142

143

## Usage Examples

144

145

### Basic Error Handling

146

147

```python

148

import wasmtime

149

150

def safe_wasm_execution():

151

"""Demonstrate basic WebAssembly error handling"""

152

153

try:

154

engine = wasmtime.Engine()

155

store = wasmtime.Store(engine)

156

157

# Try to load a WebAssembly module

158

wasm_bytes = wasmtime.wat2wasm('''

159

(module

160

(func (export "divide") (param i32 i32) (result i32)

161

local.get 0

162

local.get 1

163

i32.div_s) ;; This can trap on division by zero

164

)

165

''')

166

167

module = wasmtime.Module(engine, wasm_bytes)

168

instance = wasmtime.Instance(store, module, [])

169

170

# Get the divide function

171

divide_func = instance.exports(store)["divide"]

172

173

# Safe division

174

result = divide_func(store, 10, 2)

175

print(f"10 / 2 = {result}")

176

177

# This will cause a trap

178

result = divide_func(store, 10, 0)

179

180

except wasmtime.Trap as trap:

181

print(f"WebAssembly trap: {trap.message}")

182

print("Stack trace:")

183

for frame in trap.frames:

184

func_name = frame.func_name or f"func[{frame.func_index}]"

185

module_name = frame.module_name or "unknown"

186

print(f" at {func_name} in {module_name} (offset: {frame.module_offset})")

187

188

except wasmtime.WasmtimeError as error:

189

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

190

191

except Exception as error:

192

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

193

194

safe_wasm_execution()

195

```

196

197

### Comprehensive Error Analysis

198

199

```python

200

import wasmtime

201

202

def analyze_wasm_error(error):

203

"""Analyze and categorize WebAssembly errors"""

204

205

if isinstance(error, wasmtime.Trap):

206

print(f"TRAP: {error.message}")

207

208

# Analyze stack trace

209

if error.frames:

210

print(f"Stack depth: {len(error.frames)} frames")

211

for i, frame in enumerate(error.frames):

212

print(f" Frame {i}:")

213

print(f" Function: {frame.func_name or f'func[{frame.func_index}]'}")

214

print(f" Module: {frame.module_name or 'unknown'}")

215

print(f" Offset: 0x{frame.module_offset:x}")

216

else:

217

print(" No stack trace available")

218

219

# Check for common trap patterns

220

message_lower = error.message.lower()

221

if "division by zero" in message_lower:

222

print(" → This is a division by zero error")

223

print(" → Check divisor values before division")

224

elif "out of bounds" in message_lower:

225

print(" → This is a bounds check failure")

226

print(" → Verify array/memory access indices")

227

elif "unreachable" in message_lower:

228

print(" → Unreachable code was executed")

229

print(" → Check control flow logic")

230

231

elif isinstance(error, wasmtime.ExitTrap):

232

print(f"EXIT: Program exited with code {error.code}")

233

if error.code == 0:

234

print(" → Normal termination")

235

else:

236

print(" → Error termination")

237

238

elif isinstance(error, wasmtime.WasmtimeError):

239

print(f"RUNTIME ERROR: {error}")

240

241

# Check for common runtime errors

242

error_str = str(error).lower()

243

if "validation" in error_str:

244

print(" → WebAssembly validation failed")

245

print(" → Check module binary format and contents")

246

elif "import" in error_str:

247

print(" → Import resolution failed")

248

print(" → Verify all required imports are provided")

249

elif "type" in error_str:

250

print(" → Type mismatch error")

251

print(" → Check function signatures and value types")

252

253

else:

254

print(f"OTHER ERROR: {type(error).__name__}: {error}")

255

256

# Example usage with different error types

257

def test_various_errors():

258

"""Test different types of WebAssembly errors"""

259

260

engine = wasmtime.Engine()

261

store = wasmtime.Store(engine)

262

263

# Test 1: Division by zero trap

264

try:

265

wasm_bytes = wasmtime.wat2wasm('(module (func (export "div") (param i32 i32) (result i32) local.get 0 local.get 1 i32.div_s))')

266

module = wasmtime.Module(engine, wasm_bytes)

267

instance = wasmtime.Instance(store, module, [])

268

div_func = instance.exports(store)["div"]

269

div_func(store, 10, 0) # Division by zero

270

except Exception as e:

271

print("=== Division by Zero Test ===")

272

analyze_wasm_error(e)

273

print()

274

275

# Test 2: Memory out of bounds

276

try:

277

wasm_bytes = wasmtime.wat2wasm('''

278

(module

279

(memory 1)

280

(func (export "read_oob") (param i32) (result i32)

281

local.get 0

282

i32.load))

283

''')

284

module = wasmtime.Module(engine, wasm_bytes)

285

instance = wasmtime.Instance(store, module, [])

286

read_func = instance.exports(store)["read_oob"]

287

read_func(store, 100000) # Way out of bounds

288

except Exception as e:

289

print("=== Out of Bounds Test ===")

290

analyze_wasm_error(e)

291

print()

292

293

# Test 3: Import resolution error

294

try:

295

wasm_bytes = wasmtime.wat2wasm('''

296

(module

297

(import "env" "missing_func" (func (param i32) (result i32)))

298

(func (export "test") (result i32)

299

i32.const 42

300

call 0))

301

''')

302

module = wasmtime.Module(engine, wasm_bytes)

303

instance = wasmtime.Instance(store, module, []) # Missing import

304

except Exception as e:

305

print("=== Import Resolution Test ===")

306

analyze_wasm_error(e)

307

print()

308

309

test_various_errors()

310

```

311

312

### WASI Exit Code Handling

313

314

```python

315

import wasmtime

316

317

def run_wasi_program_with_exit_handling(wasm_path: str):

318

"""Run a WASI program with proper exit code handling"""

319

320

try:

321

# Set up WASI environment

322

wasi_config = wasmtime.WasiConfig()

323

wasi_config.inherit_argv()

324

wasi_config.inherit_env()

325

wasi_config.inherit_stdin()

326

wasi_config.inherit_stdout()

327

wasi_config.inherit_stderr()

328

329

engine = wasmtime.Engine()

330

store = wasmtime.Store(engine)

331

linker = wasmtime.Linker(engine)

332

linker.define_wasi(store, wasi_config)

333

334

# Load and instantiate WASI module

335

module = wasmtime.Module.from_file(engine, wasm_path)

336

instance = linker.instantiate(store, module)

337

338

# Run the program

339

start_func = instance.get_export(store, "_start")

340

if start_func:

341

print(f"Running WASI program: {wasm_path}")

342

start_func(store)

343

print("Program completed successfully (exit code 0)")

344

return 0

345

else:

346

print("Error: No _start function found")

347

return 1

348

349

except wasmtime.ExitTrap as exit_trap:

350

exit_code = exit_trap.code

351

if exit_code == 0:

352

print("Program completed successfully (explicit exit 0)")

353

else:

354

print(f"Program exited with error code: {exit_code}")

355

return exit_code

356

357

except wasmtime.Trap as trap:

358

print(f"Program trapped: {trap.message}")

359

360

# Print detailed stack trace

361

if trap.frames:

362

print("Stack trace:")

363

for i, frame in enumerate(trap.frames):

364

func_name = frame.func_name or f"func[{frame.func_index}]"

365

module_name = frame.module_name or "unknown"

366

print(f" {i}: {func_name} in {module_name} at 0x{frame.module_offset:x}")

367

368

return 2 # Trap exit code

369

370

except wasmtime.WasmtimeError as error:

371

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

372

return 3 # Runtime error exit code

373

374

except FileNotFoundError:

375

print(f"Error: File not found: {wasm_path}")

376

return 4 # File not found exit code

377

378

except Exception as error:

379

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

380

return 5 # Unexpected error exit code

381

382

# Example usage

383

# exit_code = run_wasi_program_with_exit_handling("my_program.wasm")

384

# sys.exit(exit_code)

385

```

386

387

### Custom Error Recovery

388

389

```python

390

import wasmtime

391

import time

392

393

class WasmExecutor:

394

def __init__(self):

395

self.engine = wasmtime.Engine()

396

self.retry_count = 0

397

self.max_retries = 3

398

399

def safe_execute(self, wasm_bytes: bytes, func_name: str, *args):

400

"""Execute WebAssembly function with error recovery"""

401

402

for attempt in range(self.max_retries + 1):

403

try:

404

store = wasmtime.Store(self.engine)

405

module = wasmtime.Module(self.engine, wasm_bytes)

406

instance = wasmtime.Instance(store, module, [])

407

408

func = instance.exports(store)[func_name]

409

result = func(store, *args)

410

411

# Reset retry count on success

412

self.retry_count = 0

413

return result

414

415

except wasmtime.Trap as trap:

416

print(f"Attempt {attempt + 1}: Trapped - {trap.message}")

417

418

# Check if this is a recoverable error

419

if self._is_recoverable_trap(trap):

420

if attempt < self.max_retries:

421

wait_time = (2 ** attempt) * 0.1 # Exponential backoff

422

print(f"Retrying in {wait_time:.1f} seconds...")

423

time.sleep(wait_time)

424

continue

425

426

# Non-recoverable or max retries exceeded

427

print(f"Giving up after {attempt + 1} attempts")

428

raise

429

430

except wasmtime.WasmtimeError as error:

431

print(f"Attempt {attempt + 1}: Runtime error - {error}")

432

433

# Most runtime errors are not recoverable

434

if "fuel" in str(error).lower() and attempt < self.max_retries:

435

print("Fuel exhausted, retrying with more fuel...")

436

continue

437

else:

438

raise

439

440

def _is_recoverable_trap(self, trap: wasmtime.Trap) -> bool:

441

"""Determine if a trap might be recoverable with retry"""

442

message = trap.message.lower()

443

444

# Some traps might be recoverable (this is application-specific)

445

recoverable_patterns = [

446

"interrupt", # Execution interrupted

447

"epoch", # Epoch deadline reached

448

"fuel" # Fuel exhausted

449

]

450

451

return any(pattern in message for pattern in recoverable_patterns)

452

453

# Example usage

454

executor = WasmExecutor()

455

456

try:

457

wasm_bytes = wasmtime.wat2wasm('''

458

(module

459

(func (export "compute") (param i32) (result i32)

460

local.get 0

461

i32.const 2

462

i32.mul))

463

''')

464

465

result = executor.safe_execute(wasm_bytes, "compute", 21)

466

print(f"Result: {result}")

467

468

except Exception as final_error:

469

print(f"Final error after all retry attempts: {final_error}")

470

```

471

472

### Error Logging and Debugging

473

474

```python

475

import wasmtime

476

import logging

477

import traceback

478

from datetime import datetime

479

480

# Configure logging

481

logging.basicConfig(

482

level=logging.DEBUG,

483

format='%(asctime)s - %(levelname)s - %(message)s'

484

)

485

logger = logging.getLogger(__name__)

486

487

class DebugWasmRunner:

488

def __init__(self, enable_debug: bool = True):

489

# Create engine with debug info if available

490

config = wasmtime.Config()

491

if enable_debug:

492

config.debug_info(True)

493

494

self.engine = wasmtime.Engine(config)

495

self.execution_log = []

496

497

def run_with_logging(self, wasm_path: str, func_name: str, *args):

498

"""Run WebAssembly function with comprehensive logging"""

499

500

execution_id = datetime.now().isoformat()

501

logger.info(f"[{execution_id}] Starting WebAssembly execution")

502

logger.info(f" Module: {wasm_path}")

503

logger.info(f" Function: {func_name}")

504

logger.info(f" Arguments: {args}")

505

506

try:

507

store = wasmtime.Store(self.engine)

508

509

# Load module with validation logging

510

logger.debug("Loading WebAssembly module...")

511

module = wasmtime.Module.from_file(self.engine, wasm_path)

512

logger.debug(f"Module loaded: {len(module.imports)} imports, {len(module.exports)} exports")

513

514

# Log imports and exports

515

for imp in module.imports:

516

logger.debug(f" Import: {imp.module}.{imp.name} ({imp.type})")

517

for exp in module.exports:

518

logger.debug(f" Export: {exp.name} ({exp.type})")

519

520

# Instantiate with logging

521

logger.debug("Instantiating module...")

522

instance = wasmtime.Instance(store, module, [])

523

logger.debug("Module instantiated successfully")

524

525

# Execute function

526

logger.debug(f"Calling function {func_name}...")

527

func = instance.exports(store)[func_name]

528

result = func(store, *args)

529

530

logger.info(f"[{execution_id}] Execution completed successfully")

531

logger.info(f" Result: {result}")

532

533

# Record successful execution

534

self.execution_log.append({

535

"id": execution_id,

536

"status": "success",

537

"module": wasm_path,

538

"function": func_name,

539

"args": args,

540

"result": result,

541

"error": None

542

})

543

544

return result

545

546

except Exception as error:

547

logger.error(f"[{execution_id}] Execution failed: {type(error).__name__}: {error}")

548

549

# Detailed error logging

550

if isinstance(error, wasmtime.Trap):

551

logger.error(f" Trap message: {error.message}")

552

logger.error(f" Stack frames: {len(error.frames)}")

553

for i, frame in enumerate(error.frames):

554

logger.error(f" Frame {i}: {frame.func_name or f'func[{frame.func_index}]'} "

555

f"in {frame.module_name or 'unknown'} at 0x{frame.module_offset:x}")

556

557

elif isinstance(error, wasmtime.ExitTrap):

558

logger.error(f" Exit code: {error.code}")

559

560

elif isinstance(error, wasmtime.WasmtimeError):

561

logger.error(f" Runtime error details: {error}")

562

563

# Log full Python traceback for debugging

564

logger.debug("Python traceback:")

565

logger.debug(traceback.format_exc())

566

567

# Record failed execution

568

self.execution_log.append({

569

"id": execution_id,

570

"status": "error",

571

"module": wasm_path,

572

"function": func_name,

573

"args": args,

574

"result": None,

575

"error": {

576

"type": type(error).__name__,

577

"message": str(error),

578

"details": self._extract_error_details(error)

579

}

580

})

581

582

raise

583

584

def _extract_error_details(self, error):

585

"""Extract detailed error information for logging"""

586

details = {}

587

588

if isinstance(error, wasmtime.Trap):

589

details["trap_message"] = error.message

590

details["stack_frames"] = []

591

for frame in error.frames:

592

details["stack_frames"].append({

593

"func_name": frame.func_name,

594

"module_name": frame.module_name,

595

"func_index": frame.func_index,

596

"module_offset": frame.module_offset

597

})

598

elif isinstance(error, wasmtime.ExitTrap):

599

details["exit_code"] = error.code

600

601

return details

602

603

def get_execution_summary(self):

604

"""Get summary of all executions"""

605

total = len(self.execution_log)

606

successful = sum(1 for log in self.execution_log if log["status"] == "success")

607

failed = total - successful

608

609

return {

610

"total_executions": total,

611

"successful": successful,

612

"failed": failed,

613

"success_rate": successful / total if total > 0 else 0,

614

"recent_errors": [log["error"] for log in self.execution_log[-5:] if log["error"]]

615

}

616

617

# Example usage

618

runner = DebugWasmRunner(enable_debug=True)

619

620

try:

621

result = runner.run_with_logging("test.wasm", "add", 5, 3)

622

print(f"Execution result: {result}")

623

except Exception as e:

624

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

625

626

# Print execution summary

627

summary = runner.get_execution_summary()

628

print(f"Execution summary: {summary}")

629

```