Skip to content

Error Handling

Uni Router provides a unified error handling mechanism. All navigation errors are wrapped in the NavigationFailure class with structured error codes.

Error Types

RouterError

Base route error class, containing error code and message:

ts
class RouterError extends Error {
	readonly code: RouterErrorCode
	readonly message: string
}

Navigation failure class, extending RouterError, with additional source and target route information:

ts
class NavigationFailure extends RouterError {
	readonly to: RouteLocation
	readonly from: RouteLocation
	readonly cause?: UniApiError
}

The cause type is UniApiError, encapsulating the failed uni-app API information:

ts
interface UniApiError {
	readonly api: string          // Name of the failed API (e.g., 'navigateTo')
	readonly cause: UniApiCause    // Original error cause
}

interface UniApiCause {
	errMsg: string                // Error description message
}

Error Codes

Error CodeDescriptionTrigger
NAVIGATION_ABORTEDNavigation aborted by guardGuard return false
NAVIGATION_CANCELLEDNavigation cancelledGuard exception, redirect limit exceeded, or insufficient page stack (back())
NAVIGATION_DUPLICATEDDuplicate navigationpush() to a page already at
ROUTE_NOT_FOUNDRoute not foundUsing undefined named route in strict mode
NAVIGATION_API_ERRORuni API call faileduni.navigateTo etc. call failed
PLUGIN_REQUIREDPlugin feature not registeredUsing params/events/animation etc. plugin-dependent features without registering the corresponding plugin
SETUP_ERRORSetup erroruseRouter() called outside setup

router.onError()

Register a global error handler callback. All navigation errors trigger it:

ts
const removeHandler = router.onError((error, to, from) => {
	switch (error.code) {
		case 'NAVIGATION_ABORTED':
			console.log('Navigation aborted')
			break
		case 'NAVIGATION_DUPLICATED':
			console.log('Duplicate navigation, ignoring')
			break
		case 'NAVIGATION_API_ERROR':
			console.error('uni API call failed', error.cause)
			break
		case 'PLUGIN_REQUIRED':
			console.error('Used plugin feature without registering plugin:', error.message)
			break
	}
})

// Remove the handler
removeHandler()

TIP

Exceptions in onError do not affect the execution of other error handlers.

try-catch Handling

You can also use try-catch when calling navigation methods:

ts
try {
	await router.push({ name: 'about' })
} catch (error) {
	if (error.code === 'NAVIGATION_DUPLICATED') {
		// Ignore duplicate navigation
		return
	}
	if (error.code === 'NAVIGATION_ABORTED') {
		console.log('Navigation aborted by guard')
		return
	}
	if (error.code === 'PLUGIN_REQUIRED') {
		console.error('Please register the corresponding plugin first:', error.message)
		return
	}
	throw error
}

Common Error Handling Scenarios

Ignore Duplicate Navigation

ts
router.onError(error => {
	if (error.code === 'NAVIGATION_DUPLICATED') return
	console.error(error)
})

Login Redirect

ts
router.onError((error, to) => {
	if (error.code === 'NAVIGATION_ABORTED' && to.meta.requireAuth) {
		router.push({ name: 'login' })
	}
})

uni API Failure Retry

ts
router.onError(async (error, to) => {
	if (error.code === 'NAVIGATION_API_ERROR') {
		console.error('Navigation failed, target:', to.fullPath)
	}
})

isNavigationFailure()

isNavigationFailure() is a type-checking utility for navigation failures. It allows you to precisely identify the type of navigation failure in catch blocks, replacing manual instanceof + code checks.

Type

ts
function isNavigationFailure(error: unknown, code?: RouterErrorCode): error is NavigationFailure

Parameters

ParameterTypeDescription
errorunknownThe caught error object
codeRouterErrorCode (optional)Error code to check against

Return Value

Returns boolean and narrows the type of error to NavigationFailure (TypeScript type guard).

Usage

Without code: check if it's any navigation failure

ts
import { isNavigationFailure } from '@meng-xi/uni-router'

try {
  await router.push({ name: 'about' })
} catch (error) {
  if (isNavigationFailure(error)) {
    console.log('Navigation failed:', error.code)
  }
}

With code: check for a specific type

ts
import { isNavigationFailure, RouterErrorCode } from '@meng-xi/uni-router'

try {
  await router.push({ name: 'about' })
} catch (error) {
  if (isNavigationFailure(error, RouterErrorCode.NAVIGATION_DUPLICATED)) {
    // Ignore duplicated navigation
    return
  }
  if (isNavigationFailure(error, RouterErrorCode.NAVIGATION_ABORTED)) {
    // Guard aborted, no action needed
    return
  }
  // Other errors
  uni.showToast({ title: 'Navigation failed', icon: 'none' })
}

Comparison with Manual Checks

ts
// Manual check (verbose)
if (error instanceof NavigationFailure && error.code === RouterErrorCode.NAVIGATION_DUPLICATED)

// Using isNavigationFailure (concise)
if (isNavigationFailure(error, RouterErrorCode.NAVIGATION_DUPLICATED))

Next Steps

Released under the MIT License.