or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

error-handling.mdevent-management.mdindex.mdnative-modules.mdnative-views.mdpermissions.mdplatform-utilities.mdutilities.md

error-handling.mddocs/

0

# Error Handling

1

2

Standardized error classes for consistent error handling across Expo modules with error codes and platform-specific messaging.

3

4

## Capabilities

5

6

### CodedError Class

7

8

General-purpose error class that provides consistent error handling with error codes for easy categorization and handling.

9

10

```typescript { .api }

11

/**

12

* General error class for all errors in Expo modules

13

* Guarantees a code field for error differentiation

14

*/

15

class CodedError extends Error {

16

/**

17

* Error code for categorizing error types

18

*/

19

code: string;

20

21

/**

22

* Additional error information

23

*/

24

info?: any;

25

26

/**

27

* Create a coded error

28

* @param code - Error code for identification

29

* @param message - Human-readable error message

30

*/

31

constructor(code: string, message: string);

32

}

33

```

34

35

**Usage Examples:**

36

37

```typescript

38

import { CodedError } from "@unimodules/core";

39

40

// Create custom errors

41

function validateInput(data: unknown) {

42

if (!data) {

43

throw new CodedError('INVALID_INPUT', 'Input data is required');

44

}

45

46

if (typeof data !== 'object') {

47

throw new CodedError('INVALID_TYPE', 'Input must be an object');

48

}

49

}

50

51

// Handle coded errors

52

try {

53

await someNativeOperation();

54

} catch (error) {

55

if (error instanceof CodedError) {

56

switch (error.code) {

57

case 'PERMISSION_DENIED':

58

showPermissionDialog();

59

break;

60

case 'NETWORK_ERROR':

61

showRetryButton();

62

break;

63

case 'INVALID_ARGUMENT':

64

showValidationError(error.message);

65

break;

66

default:

67

showGenericError(error.message);

68

}

69

} else {

70

// Handle non-coded errors

71

showGenericError('An unexpected error occurred');

72

}

73

}

74

75

// Add additional error information

76

function createDetailedError(code: string, message: string, details: any) {

77

const error = new CodedError(code, message);

78

error.info = details;

79

return error;

80

}

81

82

const error = createDetailedError(

83

'API_ERROR',

84

'Failed to fetch user data',

85

{

86

endpoint: '/api/users/123',

87

statusCode: 404,

88

timestamp: new Date().toISOString()

89

}

90

);

91

```

92

93

### UnavailabilityError Class

94

95

Specialized error class for features that are unavailable, unsupported, or not implemented on the current platform.

96

97

```typescript { .api }

98

/**

99

* Error for unavailable, unsupported, or unimplemented properties

100

* Automatically includes platform information

101

*/

102

class UnavailabilityError extends CodedError {

103

/**

104

* Create an unavailability error

105

* @param moduleName - Name of the module

106

* @param propertyName - Name of the unavailable property/method

107

*/

108

constructor(moduleName: string, propertyName: string);

109

}

110

```

111

112

**Usage Examples:**

113

114

```typescript

115

import { UnavailabilityError, Platform } from "@unimodules/core";

116

117

// Throw for unsupported features

118

class CameraModule {

119

static async takePictureAsync() {

120

if (Platform.OS === 'web') {

121

throw new UnavailabilityError('Camera', 'takePictureAsync');

122

}

123

// Native implementation

124

return NativeModulesProxy.Camera.takePictureAsync();

125

}

126

127

static async recordVideoAsync() {

128

if (!Platform.select({ ios: true, android: true, default: false })) {

129

throw new UnavailabilityError('Camera', 'recordVideoAsync');

130

}

131

return NativeModulesProxy.Camera.recordVideoAsync();

132

}

133

}

134

135

// Handle unavailability errors

136

try {

137

await CameraModule.takePictureAsync();

138

} catch (error) {

139

if (error instanceof UnavailabilityError) {

140

console.warn(`Feature not available: ${error.message}`);

141

// Show alternative UI or disable feature

142

showFeatureUnavailableMessage();

143

}

144

}

145

146

// Conditional feature checking

147

function createFeatureProxy(moduleName: string) {

148

return new Proxy({}, {

149

get(target, propertyName: string) {

150

const module = NativeModulesProxy[moduleName];

151

if (!module || !(propertyName in module)) {

152

throw new UnavailabilityError(moduleName, propertyName);

153

}

154

return module[propertyName];

155

}

156

});

157

}

158

```

159

160

### Error Code Standards

161

162

Common error codes used throughout the Expo ecosystem:

163

164

```typescript { .api }

165

/**

166

* Standard error codes used across Expo modules

167

*/

168

type StandardErrorCodes =

169

| 'ERR_UNAVAILABLE' // Feature not available on platform

170

| 'ERR_DEPRECATED_API' // API has been deprecated/removed

171

| 'ERR_INVALID_ARGUMENT' // Invalid argument provided

172

| 'ERR_PERMISSION_DENIED' // Permission required but not granted

173

| 'ERR_NETWORK_ERROR' // Network operation failed

174

| 'ERR_FILE_NOT_FOUND' // File system operation failed

175

| 'ERR_OPERATION_CANCELLED' // User cancelled operation

176

| 'ERR_TIMEOUT' // Operation timed out

177

| 'ERR_INITIALIZATION' // Module failed to initialize

178

| 'ERR_PLATFORM_SPECIFIC'; // Platform-specific error

179

```

180

181

**Usage Examples:**

182

183

```typescript

184

import { CodedError } from "@unimodules/core";

185

186

// Use standard error codes

187

function validatePermission(permission: string) {

188

if (!permission) {

189

throw new CodedError('ERR_INVALID_ARGUMENT', 'Permission name is required');

190

}

191

}

192

193

async function requestWithTimeout<T>(operation: Promise<T>, timeout: number): Promise<T> {

194

const timeoutPromise = new Promise<never>((_, reject) => {

195

setTimeout(() => {

196

reject(new CodedError('ERR_TIMEOUT', `Operation timed out after ${timeout}ms`));

197

}, timeout);

198

});

199

200

return Promise.race([operation, timeoutPromise]);

201

}

202

203

// Handle standard error codes

204

function handleStandardError(error: CodedError) {

205

switch (error.code) {

206

case 'ERR_PERMISSION_DENIED':

207

return 'Permission required. Please grant access in settings.';

208

case 'ERR_NETWORK_ERROR':

209

return 'Network error. Please check your connection.';

210

case 'ERR_TIMEOUT':

211

return 'Operation timed out. Please try again.';

212

case 'ERR_UNAVAILABLE':

213

return 'This feature is not available on your device.';

214

default:

215

return `Error: ${error.message}`;

216

}

217

}

218

```

219

220

## Advanced Usage

221

222

### Error Factory Pattern

223

224

```typescript

225

import { CodedError, UnavailabilityError } from "@unimodules/core";

226

227

class ErrorFactory {

228

static createPermissionError(permission: string): CodedError {

229

return new CodedError(

230

'ERR_PERMISSION_DENIED',

231

`${permission} permission is required but not granted`

232

);

233

}

234

235

static createNetworkError(details?: any): CodedError {

236

const error = new CodedError('ERR_NETWORK_ERROR', 'Network request failed');

237

if (details) {

238

error.info = details;

239

}

240

return error;

241

}

242

243

static createValidationError(field: string, value: any): CodedError {

244

const error = new CodedError(

245

'ERR_INVALID_ARGUMENT',

246

`Invalid value for field '${field}'`

247

);

248

error.info = { field, value };

249

return error;

250

}

251

252

static createUnavailableError(module: string, method: string): UnavailabilityError {

253

return new UnavailabilityError(module, method);

254

}

255

}

256

257

// Usage

258

throw ErrorFactory.createPermissionError('CAMERA');

259

throw ErrorFactory.createNetworkError({ statusCode: 500, endpoint: '/api/data' });

260

```

261

262

### Error Recovery Patterns

263

264

```typescript

265

import { CodedError, UnavailabilityError } from "@unimodules/core";

266

267

class ErrorRecovery {

268

static async withRetry<T>(

269

operation: () => Promise<T>,

270

maxRetries: number = 3,

271

delay: number = 1000

272

): Promise<T> {

273

let lastError: Error;

274

275

for (let attempt = 1; attempt <= maxRetries; attempt++) {

276

try {

277

return await operation();

278

} catch (error) {

279

lastError = error;

280

281

// Don't retry certain error types

282

if (error instanceof UnavailabilityError ||

283

(error instanceof CodedError && error.code === 'ERR_PERMISSION_DENIED')) {

284

throw error;

285

}

286

287

if (attempt < maxRetries) {

288

await new Promise(resolve => setTimeout(resolve, delay * attempt));

289

}

290

}

291

}

292

293

throw new CodedError('ERR_MAX_RETRIES_EXCEEDED',

294

`Operation failed after ${maxRetries} attempts: ${lastError.message}`);

295

}

296

297

static async withFallback<T>(

298

primary: () => Promise<T>,

299

fallback: () => Promise<T>

300

): Promise<T> {

301

try {

302

return await primary();

303

} catch (error) {

304

if (error instanceof UnavailabilityError) {

305

console.warn(`Primary method unavailable, using fallback: ${error.message}`);

306

return await fallback();

307

}

308

throw error;

309

}

310

}

311

}

312

313

// Usage

314

const result = await ErrorRecovery.withRetry(async () => {

315

return await fetch('/api/data');

316

});

317

318

const data = await ErrorRecovery.withFallback(

319

() => NativeModulesProxy.Storage.getSecureItem('key'),

320

() => AsyncStorage.getItem('key')

321

);

322

```

323

324

## Types

325

326

```typescript { .api }

327

interface ErrorInfo {

328

[key: string]: any;

329

}

330

331

interface CodedErrorConstructor {

332

new (code: string, message: string): CodedError;

333

prototype: CodedError;

334

}

335

336

interface UnavailabilityErrorConstructor {

337

new (moduleName: string, propertyName: string): UnavailabilityError;

338

prototype: UnavailabilityError;

339

}

340

```