or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-loading.mderror-handling.mdindex.mdnavigation-links.mdpath-search-utils.mdreact-components.mdreact-hooks.mdroute-definition.mdrouter-creation.mdssr.md

error-handling.mddocs/

0

# Error Handling

1

2

Comprehensive error handling with boundaries, not found handling, custom error components, and error recovery mechanisms for robust routing applications.

3

4

## Capabilities

5

6

### Error Boundaries

7

8

React error boundaries for catching and handling route errors with recovery capabilities.

9

10

```typescript { .api }

11

/**

12

* Error boundary for catching and handling route errors

13

* @param props - Error boundary configuration

14

* @returns JSX element with error boundary functionality

15

*/

16

function CatchBoundary(props: CatchBoundaryProps): JSX.Element;

17

18

interface CatchBoundaryProps {

19

/** Function to get reset key for boundary reset */

20

getResetKey: () => string | number;

21

/** Child components to protect */

22

children: React.ReactNode;

23

/** Custom error component to render */

24

errorComponent?: ErrorRouteComponent;

25

/** Error handler callback */

26

onCatch?: (error: Error, errorInfo: React.ErrorInfo) => void;

27

}

28

29

/**

30

* Default error component for displaying errors

31

* @param props - Error component props

32

* @returns JSX element displaying error information

33

*/

34

function ErrorComponent(props: ErrorComponentProps): JSX.Element;

35

36

interface ErrorComponentProps {

37

/** The error that occurred */

38

error: any;

39

/** Error info from React */

40

info?: { componentStack: string };

41

/** Function to reset the error boundary */

42

reset?: () => void;

43

}

44

```

45

46

**Usage Examples:**

47

48

```typescript

49

import { CatchBoundary, ErrorComponent } from "@tanstack/react-router";

50

51

// Basic error boundary

52

<CatchBoundary

53

getResetKey={() => window.location.pathname}

54

errorComponent={ErrorComponent}

55

onCatch={(error, errorInfo) => {

56

console.error("Route error:", error);

57

// Send to error reporting service

58

errorReporter.captureException(error, {

59

extra: { errorInfo, route: window.location.pathname },

60

});

61

}}

62

>

63

<App />

64

</CatchBoundary>

65

66

// Custom error component

67

function CustomErrorComponent({ error, reset }) {

68

return (

69

<div className="error-container">

70

<h2>Something went wrong</h2>

71

<details>

72

<summary>Error details</summary>

73

<pre>{error.message}</pre>

74

<pre>{error.stack}</pre>

75

</details>

76

<button onClick={reset} className="retry-button">

77

Try again

78

</button>

79

</div>

80

);

81

}

82

83

// Error boundary with custom component

84

<CatchBoundary

85

getResetKey={() => Date.now()}

86

errorComponent={CustomErrorComponent}

87

>

88

<Routes />

89

</CatchBoundary>

90

```

91

92

### Not Found Error Handling

93

94

Specialized error handling for 404 not found errors with custom fallbacks.

95

96

```typescript { .api }

97

/**

98

* Create a not found error

99

* @param options - Not found error options

100

* @returns NotFoundError instance

101

*/

102

function notFound<TRouterContext = unknown>(

103

options?: NotFoundErrorOptions<TRouterContext>

104

): NotFoundError;

105

106

/**

107

* Type guard for not found errors

108

* @param obj - Object to check

109

* @returns Whether object is a not found error

110

*/

111

function isNotFound(obj: any): obj is NotFoundError;

112

113

interface NotFoundError extends Error {

114

/** Error code identifier */

115

routerCode: "NOT_FOUND";

116

/** Whether error was thrown in production */

117

isNotFound: true;

118

/** Additional data */

119

data?: any;

120

}

121

122

interface NotFoundErrorOptions<TRouterContext = unknown> {

123

/** Additional data to include */

124

data?: any;

125

}

126

127

/**

128

* Boundary specifically for handling not found errors

129

* @param props - Not found boundary props

130

* @returns JSX element with not found error handling

131

*/

132

function CatchNotFound(props: CatchNotFoundProps): JSX.Element;

133

134

interface CatchNotFoundProps {

135

/** Fallback component for not found errors */

136

fallback?: (error: NotFoundError) => React.ReactElement;

137

/** Error handler callback */

138

onCatch?: (error: Error, errorInfo: React.ErrorInfo) => void;

139

/** Child components */

140

children: React.ReactNode;

141

}

142

143

/**

144

* Default global not found component

145

* @returns JSX element for 404 errors

146

*/

147

function DefaultGlobalNotFound(): JSX.Element;

148

```

149

150

**Usage Examples:**

151

152

```typescript

153

import { notFound, isNotFound, CatchNotFound, DefaultGlobalNotFound } from "@tanstack/react-router";

154

155

// Throw not found in loader

156

const Route = createRoute({

157

path: "/posts/$postId",

158

loader: async ({ params }) => {

159

const post = await fetchPost(params.postId);

160

161

if (!post) {

162

throw notFound({

163

data: {

164

postId: params.postId,

165

message: "Post not found",

166

},

167

});

168

}

169

170

return { post };

171

},

172

});

173

174

// Handle not found in component

175

function PostLoader() {

176

try {

177

const { post } = useLoaderData();

178

return <PostDetail post={post} />;

179

} catch (error) {

180

if (isNotFound(error)) {

181

return <div>Post not found: {error.data?.postId}</div>;

182

}

183

throw error; // Re-throw other errors

184

}

185

}

186

187

// Not found boundary

188

<CatchNotFound

189

fallback={(error) => (

190

<div className="not-found">

191

<h1>404 - Page Not Found</h1>

192

<p>{error.data?.message || "The requested page could not be found."}</p>

193

<Link to="/">Go Home</Link>

194

</div>

195

)}

196

onCatch={(error, errorInfo) => {

197

console.log("Not found error:", error.data);

198

}}

199

>

200

<Routes />

201

</CatchNotFound>

202

203

// Using default not found component

204

function App() {

205

return (

206

<Router>

207

<Routes>

208

<Route path="*" component={DefaultGlobalNotFound} />

209

</Routes>

210

</Router>

211

);

212

}

213

```

214

215

### Route-Level Error Components

216

217

Error components specifically for route-level error handling.

218

219

```typescript { .api }

220

/**

221

* Route error component type

222

*/

223

type ErrorRouteComponent = React.ComponentType<{

224

error: Error;

225

info: { componentStack: string };

226

reset: () => void;

227

}>;

228

229

/**

230

* Not found route component type

231

*/

232

type NotFoundRouteComponent = React.ComponentType<{

233

data?: any;

234

}>;

235

```

236

237

**Usage Examples:**

238

239

```typescript

240

// Route with error component

241

const Route = createRoute({

242

path: "/risky-route",

243

loader: async () => {

244

// This might throw an error

245

const data = await riskyApiCall();

246

return { data };

247

},

248

component: RiskyComponent,

249

errorComponent: ({ error, reset }) => (

250

<div>

251

<h2>Error in risky route</h2>

252

<p>{error.message}</p>

253

<button onClick={reset}>Retry</button>

254

<Link to="/">Go Home</Link>

255

</div>

256

),

257

});

258

259

// Route with not found component

260

const Route = createRoute({

261

path: "/users/$userId",

262

loader: async ({ params }) => {

263

const user = await fetchUser(params.userId);

264

if (!user) {

265

throw notFound({ data: { userId: params.userId } });

266

}

267

return { user };

268

},

269

component: UserProfile,

270

notFoundComponent: ({ data }) => (

271

<div>

272

<h2>User Not Found</h2>

273

<p>User with ID "{data?.userId}" does not exist.</p>

274

<Link to="/users">View All Users</Link>

275

</div>

276

),

277

});

278

```

279

280

### Error Recovery and Reset

281

282

Utilities for recovering from errors and resetting error states.

283

284

```typescript { .api }

285

/**

286

* Error boundary reset utilities

287

*/

288

interface ErrorBoundaryReset {

289

/** Reset the error boundary */

290

reset: () => void;

291

/** Get current reset key */

292

getResetKey: () => string | number;

293

}

294

295

/**

296

* Router-level error handling

297

*/

298

interface RouterErrorHandling {

299

/** Default error handler for all routes */

300

defaultOnCatch?: (error: Error, errorInfo: React.ErrorInfo) => void;

301

/** Default error component */

302

defaultErrorComponent?: ErrorRouteComponent;

303

/** Default not found component */

304

defaultNotFoundComponent?: NotFoundRouteComponent;

305

}

306

```

307

308

**Usage Examples:**

309

310

```typescript

311

// Router with global error handling

312

const router = createRouter({

313

routeTree,

314

defaultErrorComponent: ({ error, reset }) => (

315

<div className="global-error">

316

<h1>Application Error</h1>

317

<p>{error.message}</p>

318

<button onClick={reset}>Reset Application</button>

319

</div>

320

),

321

defaultNotFoundComponent: () => (

322

<div className="global-not-found">

323

<h1>Page Not Found</h1>

324

<Link to="/">Return Home</Link>

325

</div>

326

),

327

defaultOnCatch: (error, errorInfo) => {

328

// Global error logging

329

console.error("Global route error:", error, errorInfo);

330

errorReporter.captureException(error, {

331

tags: { type: "route_error" },

332

extra: errorInfo,

333

});

334

},

335

});

336

337

// Component with error recovery

338

function RecoverableComponent() {

339

const [retryCount, setRetryCount] = useState(0);

340

const navigate = useNavigate();

341

342

const handleError = useCallback((error: Error) => {

343

if (retryCount < 3) {

344

// Auto-retry up to 3 times

345

setTimeout(() => {

346

setRetryCount(prev => prev + 1);

347

window.location.reload();

348

}, 1000);

349

} else {

350

// Navigate to error page after max retries

351

navigate({ to: "/error", state: { error: error.message } });

352

}

353

}, [retryCount, navigate]);

354

355

return (

356

<CatchBoundary

357

getResetKey={() => retryCount}

358

onCatch={handleError}

359

>

360

<RiskyComponent />

361

</CatchBoundary>

362

);

363

}

364

```

365

366

### Error Serialization

367

368

Utilities for serializing errors, particularly useful for SSR.

369

370

```typescript { .api }

371

/**

372

* Default error serializer for SSR and transport

373

* @param error - Error to serialize

374

* @returns Serialized error object

375

*/

376

function defaultSerializeError(error: Error): SerializedError;

377

378

interface SerializedError {

379

name: string;

380

message: string;

381

stack?: string;

382

}

383

```

384

385

**Usage Examples:**

386

387

```typescript

388

import { defaultSerializeError } from "@tanstack/react-router";

389

390

// Serialize errors for API responses

391

async function apiErrorHandler(error: Error) {

392

const serialized = defaultSerializeError(error);

393

394

return {

395

success: false,

396

error: serialized,

397

timestamp: Date.now(),

398

};

399

}

400

401

// Custom error serializer

402

function customSerializeError(error: Error) {

403

const base = defaultSerializeError(error);

404

405

return {

406

...base,

407

code: error.code || "UNKNOWN_ERROR",

408

timestamp: Date.now(),

409

userAgent: navigator.userAgent,

410

};

411

}

412

```

413

414

### Router State Utilities

415

416

Utilities for managing router state and initialization.

417

418

```typescript { .api }

419

/**

420

* Get initial router state for a given location

421

* @param location - Parsed location object

422

* @returns Initial router state

423

*/

424

function getInitialRouterState(location: ParsedLocation): RouterState;

425

```

426

427

**Usage Examples:**

428

429

```typescript

430

import { getInitialRouterState } from "@tanstack/react-router";

431

432

// Create initial state for SSR

433

function createServerState(url: string) {

434

const location = parseLocation(url);

435

const initialState = getInitialRouterState(location);

436

437

return {

438

...initialState,

439

isServer: true,

440

};

441

}

442

443

// Initialize router with custom state

444

const router = createRouter({

445

routeTree,

446

initialState: getInitialRouterState(currentLocation),

447

});

448

```

449

450

### Error Class Types

451

452

Specific error classes for different routing scenarios.

453

454

```typescript { .api }

455

/**

456

* Search parameter validation error

457

* Thrown when search parameter validation fails

458

*/

459

class SearchParamError extends Error {

460

name: "SearchParamError";

461

constructor(message: string);

462

}

463

464

/**

465

* Path parameter validation error

466

* Thrown when path parameter validation fails

467

*/

468

class PathParamError extends Error {

469

name: "PathParamError";

470

constructor(message: string);

471

}

472

```

473

474

**Usage Examples:**

475

476

```typescript

477

import { SearchParamError, PathParamError } from "@tanstack/react-router";

478

479

// Route with parameter validation

480

const Route = createRoute({

481

path: "/items/$itemId",

482

validateSearch: (search) => {

483

const page = Number(search.page);

484

if (isNaN(page) || page < 1) {

485

throw new SearchParamError("Page must be a positive number");

486

}

487

return { page };

488

},

489

loader: ({ params }) => {

490

if (!params.itemId.match(/^[a-zA-Z0-9]+$/)) {

491

throw new PathParamError("Invalid item ID format");

492

}

493

return fetchItem(params.itemId);

494

},

495

errorComponent: ({ error }) => {

496

if (error instanceof SearchParamError) {

497

return <div>Invalid search parameters: {error.message}</div>;

498

}

499

if (error instanceof PathParamError) {

500

return <div>Invalid path parameters: {error.message}</div>;

501

}

502

return <div>Unexpected error: {error.message}</div>;

503

},

504

});

505

```

506

507

## Types

508

509

### Error Component Types

510

511

```typescript { .api }

512

interface ErrorRouteProps {

513

error: Error;

514

info: { componentStack: string };

515

reset: () => void;

516

}

517

518

interface NotFoundRouteProps {

519

data?: any;

520

}

521

522

type ErrorRouteComponent = React.ComponentType<ErrorRouteProps>;

523

type NotFoundRouteComponent = React.ComponentType<NotFoundRouteProps>;

524

```

525

526

### Error State Types

527

528

```typescript { .api }

529

interface RouteErrorState {

530

error?: Error;

531

errorInfo?: React.ErrorInfo;

532

hasError: boolean;

533

errorBoundaryKey: string | number;

534

}

535

536

interface ErrorBoundaryState {

537

hasError: boolean;

538

error?: Error;

539

errorInfo?: React.ErrorInfo;

540

resetKey: string | number;

541

}

542

```

543

544

### Error Handling Configuration

545

546

```typescript { .api }

547

interface ErrorHandlingConfig {

548

defaultErrorComponent?: ErrorRouteComponent;

549

defaultNotFoundComponent?: NotFoundRouteComponent;

550

defaultOnCatch?: (error: Error, errorInfo: React.ErrorInfo) => void;

551

errorSerializer?: (error: Error) => any;

552

}

553

```