Network errors, empty states, and edge cases show user-friendly messages
Why it matters
Reviewers deliberately test on degraded networks and with edge-case data. Empty catch blocks (CWE-390) that swallow errors produce blank white screens — a visible failure that signals low quality and triggers rejection under Apple's guideline 2.1. ISO 25010:2011 fault-tolerance requires systems to continue operating under abnormal conditions. Beyond rejection risk, raw error messages ({error.message}) leak implementation details and destroy user trust. A screen that shows nothing when the network is bad is indistinguishable from a bug.
Severity rationale
High because empty catch blocks and missing error states produce blank screens that reviewers directly observe, causing rejection under guideline 2.1.
Remediation
Implement all four UI states for every data-fetching screen.
// src/screens/FeedScreen.tsx
export default function FeedScreen() {
const { data, isLoading, error, refetch } = useFeed();
if (isLoading) return <ActivityIndicator />;
if (error) return (
<View style={styles.center}>
<Text>Couldn't load your feed.</Text>
<Button title="Try again" onPress={refetch} />
</View>
);
if (!data?.length) return <EmptyState message="Nothing here yet — check back soon." />;
return <FlatList data={data} renderItem={renderItem} />;
}
Never render {error.message} or {error.toString()} directly. Test every screen with airplane mode enabled on the simulator before submission.
Detection
- ID:
error-states-handled - Severity:
high - What to look for: Count all relevant instances and enumerate each. Search for
catchblocks that are empty or only callconsole.log(). Look for screens that fetch data but have no empty-state UI (no results, no content). Check for raw error objects being rendered to the user:{error.message},{err.toString()}, JSON-stringified objects displayed in the UI. Look forundefinedornullrendered where JSX expects a string. Also look for "Something went wrong" text with no actionable retry option. In Flutter, checkFutureBuilderandStreamBuilderfor missingsnapshot.hasErrorandsnapshot.connectionState == ConnectionState.nonehandling. - Pass criteria: All data-fetching screens have: a loading state, a non-empty content state, an error state with a user-friendly message and retry option, and an empty state (if the data set can be empty). At least 1 implementation must be verified.
- Fail criteria: Empty
catchblocks that swallow errors silently; raw error messages or stack traces visible in the UI; screens that show a blank white area when data fails to load; no retry mechanism after network errors. - Skip (N/A) when: Never.
- Detail on fail:
"ProfileScreen catch block only calls console.log — network errors show a blank screen"or"FeedScreen has no empty-state UI — new users see a completely blank feed with no guidance" - Remediation: Reviewers test on real networks (sometimes deliberately bad ones) and with edge-case data.
- For every data-fetching screen, implement all four states:
if (isLoading) return <LoadingSpinner />; if (error) return <ErrorView message="Couldn't load data" onRetry={refetch} />; if (!data?.length) return <EmptyState message="Nothing here yet" />; return <DataList data={data} />; - Never render
{error.message}or{error.toString()}directly — show a friendly message instead - Add a retry button to all error states
- Test by disabling network access on the simulator/device and navigating through the app
- For every data-fetching screen, implement all four states:
External references
- cwe · CWE-390 — Detection of Error Condition Without Action
- iso-25010:2011 · fault-tolerance — Fault Tolerance (ISO 25010 Reliability)
Taxons
History
- 2026-04-18·v1.0.0·Initial import from app-store-review-blockers·automated