alibaba/ARouter · error · NoRouteFoundException
No postcard!
Error message
No postcard!
What it means
LogisticsCenter.completion() fills in a Postcard's route metadata; it throws NoRouteFoundException 'No postcard!' when handed a null Postcard. This is a fail-fast guard: navigation cannot proceed without a Postcard built via ARouter.build().
Source
Thrown at arouter-api/src/main/java/com/alibaba/android/arouter/core/LogisticsCenter.java:274
addRouteGroupDynamic(postcard.getGroup(), null);
} catch (Exception e) {
throw new HandlerException(
TAG + "Fatal exception when loading group meta. [" + describeFailure(e) + "]",
e
);
}
return Warehouse.routes.containsKey(postcard.getPath());
}
/**
* Completion the postcard by route metas
*
* @param postcard Incomplete postcard, should complete by this method.
*/
public synchronized static void completion(Postcard postcard) {
if (null == postcard) {
throw new NoRouteFoundException(TAG + "No postcard!");
}
RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
if (null == routeMeta) {
// Maybe its does't exist, or didn't load.
if (!Warehouse.groupsIndex.containsKey(postcard.getGroup())) {
throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
} else {
// Load route and cache it into memory, then delete from metas.
try {
if (ARouter.debuggable()) {
logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
}
addRouteGroupDynamic(postcard.getGroup(), null);
if (ARouter.debuggable()) {
logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] has already been loaded, trigger by [%s]", postcard.getGroup(), postcard.getPath()));View on GitHub (pinned to 84f451d244)
Solutions
- Ensure the Postcard comes from ARouter.getInstance().build(path) and is non-null before navigating
- Null-check inputs in wrapper methods that derive the path from URIs or user data
- Log and return early instead of forwarding a null Postcard to the navigation pipeline
Example fix
// before
Postcard postcard = uri != null ? build(uri) : null;
LogisticsCenter.completion(postcard); // NPE-style throw
// after
Postcard postcard = uri != null ? build(uri) : null;
if (postcard != null) {
LogisticsCenter.completion(postcard);
} Defensive patterns
Strategy: type-guard
Validate before calling
if (postcard == null) {
Log.w(TAG, "no postcard built, skipping navigation");
return;
} Type guard
boolean isValid(Postcard p) { return p != null && p.getPath() != null && !p.getPath().isEmpty(); } Try / catch
try {
LogisticsCenter.completion(postcard);
} catch (NoRouteFoundException e) {
Log.w(TAG, "completion skipped: " + e.getMessage());
} Prevention
- Only build Postcards via ARouter.build() and null-check the result
- Null-check path/URI inputs before building the postcard
- Avoid conditional postcard construction in wrappers
When it happens
Trigger: Passing null to completion(), e.g. a navigation helper that builds a Postcard conditionally and forwards null when a path/group is empty.
Common situations: Custom navigation wrappers where build() result is assigned conditionally; refactored code where an earlier null check on the URI/path was removed.
Related errors
- Interceptor initialization failure must have a cause.
- TimeUnit must not be null.
- There is no route match the path [<path>], in group [<group>
- String.format(tipText, key)
- Interceptor timeout has already been scheduled.
AI-assisted analysis of alibaba/ARouter@84f451d244 (2026-09-06).
Data as JSON: /api/errors/adce9c618c284549.
Report an issue: GitHub.