Skip to content

fix(mobile): stop reporting expected conditions to Sentry - #4831

Open
iscekic wants to merge 7 commits into
mainfrom
sentry-noise-fff3
Open

fix(mobile): stop reporting expected conditions to Sentry#4831
iscekic wants to merge 7 commits into
mainfrom
sentry-noise-fff3

Conversation

@iscekic

@iscekic iscekic commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

What: stop reporting two classes of expected user-environment failures to Sentry from apps/mobile — AppsFlyer event-delivery transport failures, and the KiloClaw onboarding identity step's GPS lookup failures. The production change is three lines in two files (two error callbacks swapped for the existing noop, one captureException deleted), plus unit tests and one vitest include line. No UI, copy, state, or control flow changes.

Why: production Sentry noise. Governing rule applied throughout: report only what a developer could act on.

How: per-issue dispositions, each traced against the live code path on main:

Issue Disposition Evidence
KILO-APP-1ZAppsFlyer event "…" failed: Failed to connect …:443 Fixed here Both logEvent error callbacks (trackEvent and the pending-event drain in appsflyer.ts) are now noop. A delivery failure is a transport condition (offline, DNS-blocked, ad-blocker, corporate proxy) that the SDK queues and retries itself; the JS error callback carries an untyped bare message string with no structured discriminator, so a transport/config split is not reliably possible.
KILO-APP-27Error: timeout Fixed here The identity step's own 10 s GPS_TIMEOUT_MS race rejects into the outer catch of handleGpsPress; its Sentry.captureException is removed. The user is told exactly what happened via locationFeedback ("Could not get your location. Enter it manually."), unchanged.
KILO-APP-2ZLocation request failed due to unsatisfied device settings Fixed here expo-location's rejection lands in the same outer catch; the same one removal covers it.
KILO-APP-26, -7, -V — push-token fetch failures Dropped — no live reporting path on main Notifications.getExpoPushTokenAsync is called from exactly two places, both awaited inside try blocks: notifications-step.tsx (catch renders an inline message with Try again / Skip for now) and notifications-screen.tsx (catch shows a "Could not enable notifications" toast). getDevicePushToken rejections are caught by React Query and rendered via isError. No captureException exists in notifications.ts, notifications-screen.tsx, or notifications-step.tsx, and the global TanStack error hooks never touch Sentry.
KILO-APP-22WebBrowser's auth session is in an invalid state… Dropped — no live reporting path on main All six openAuthSessionAsync call sites catch and none reports to Sentry. The error only originates in expo-web-browser's Android polyfill, which was already removed from the device-auth path that produced these events in #4376.

No actionable report was removed. Deliberately retained: AppsFlyer init failed (initSdk error callback — catches a bad dev key / app id / SDK start failure), AppsFlyer purchase connector failed, and the identity step's inner captureException(validateError), which reports failures of the first-party kiloclaw.validateWeatherLocation tRPC procedure.

Observed but not fixed (KILO-APP-22 nuance): one openAuthSessionAsync site — the Open GitHub button at new-session-repository-section.tsx:79 via agent-chat/new.tsx — has no in-flight re-entry guard, so an Android double-tap there can still throw and show its (caught, recoverable) toast. Left alone deliberately: that site emits zero Sentry events, so it sits outside this PR's Sentry-noise mandate; the observable outcome is already a recoverable toast plus retry; and adding button state would be a user-visible behaviour change in a PR whose stated invariant is that user-visible behaviour does not change.

Acceptance criterion 3 (push-token failures surface handled; registration behaviour unchanged apart from reporting) is discharged by the code evidence above on main, not by a device observation — no push-token code changed in this PR.

Unit coverage: the new negative tests were verified red-before / green-after against the production edits — against unmodified code they fail with captureException … called 1 times carrying the exact production errors, proving they reach the code under test rather than passing vacuously. Full apps/mobile checks green: format, typecheck, lint (993 files, 0 errors), knip, and 278 test files / 2343 tests; the new identity-step.test.tsx runs in the mobile-pure project (its include line is part of this PR — without it the suite would silently never execute, now recorded as a workflow learning).

Verification

  • apps/mobile green: pnpm format, pnpm typecheck, pnpm lint (993 files, 0 errors), pnpm check:unused, pnpm test (278 files / 2343 tests — identity-step.test.tsx executing in mobile-pure), git diff --check
  • On-device E2E (iOS 26.5, iPhone 17 Pro simulator, fresh trial-eligible account) — VERIFICATION PASSED., independent e2e-verifier round against the final head; byte-identical git baseline before/after:
    • R1 (GPS failure UX, KILO-APP-27/-2Z) — PASS. The identity step's outer catch was driven deterministically (iOS 26.5 simulators cannot starve getCurrentPositionAsyncsimctl location clear is non-functional, so Location Services were toggled off to reach the identical catch; recorded as a workflow learning). Feedback line exactly Could not get your location. Enter it manually., no red box/crash/toast, input still editable, Continue enabled. Screenshots: r1-feedback-line-final.png, r1-spinner-mid.png.
    • R2 (GPS happy path) — PASS, backend-resolved variant: 52.37,4.90 → input filled Amsterdam, The Netherlands with the weather feedback line. Screenshot: r2-happy-path.png.
    • R3 (AppsFlyer regression) — PASS: cold launch → KiloClaw tab → identity step; no crash, no red box, no new errors in the mobile pane (one pre-existing benign RN-bridge WARN that confirms initSdk ran behind consent). Screenshot: r3-cold-launch-identity.png.
    • R4 (push registration, AC3) — PASS on the success branch, binding per the §2.2 decision: Profile → Notifications → Enable notifications → permission allowed → token fetch succeeded → Push notifications are on this device. No crash or unhandled rejection. Screenshot: r4-enabled-state.png.
    • Android O1/O2 intentionally dropped (non-gating): never on Android, and O1's failure class was already produced on iOS in R1.
    • Screenshots named above were captured by the verifier during the round and retained as workflow evidence.

Visual Changes

N/A

Reviewer Notes

Feature-state matrix: not applicable — this PR adds no user-facing feature; it removes error-reporting side effects from existing flows and changes no UI, copy, state, or control flow.

Focus areas: the two retained AppsFlyer reports and the retained validateWeatherLocation capture are the signal this PR deliberately keeps; the identity-step diff should be exactly "one capture removed, everything else byte-identical".

iscekic added 3 commits July 28, 2026 16:40
…ly skip new tests

A test file added in a directory no include glob covers passes CI
without ever running: vitest.config.ts composes two projects with
enumerated includes, and a path outside every glob matches no project
and is skipped with no warning. Symptom/cause/fix recorded; the fix
side lands with the identity-step test in this section.
A failed logEvent delivery is a transport failure (offline, DNS-blocked,
ad-blocked, proxied) that the AppsFlyer SDK queues and retries itself;
the JS error callback carries a bare platform message string with no
structured discriminator, so no developer action is possible and every
report was noise (KILO-APP-1Z). Both logEvent error callbacks - the
trackEvent site and the pending-event drain - are now the existing noop.

Actionable integration failures still report: initSdk's error callback
("AppsFlyer init failed") and the purchase connector's are untouched.

Tests: transport failure not reported, queued-drain failure not
reported, and init failure still reported with its message intact.
…Sentry

Everything reaching the outer catch of handleGpsPress is an expected
user-environment condition - the app's own 10s GPS timeout (KILO-APP-27),
location services off, unsatisfied device settings (KILO-APP-2Z) - and
the UI already tells the user exactly what happened via locationFeedback
("Could not get your location. Enter it manually."). Nothing there is
developer-actionable, so the captureException is removed; the feedback
message, status, and loading handling are byte-identical.

The inner catch's validateWeatherLocation capture stays: that procedure
is first-party, so its failures are actionable and must keep reporting.

Tests: positive control (validateWeatherLocation rejection still reports
the exact error object) plus both production expected-condition messages
asserting no report, no backend mutation, and that the handler ran. The
new suite needs a mobile-pure include for src/components/kiloclaw -
added as the narrowest matching glob (see the committed learning).
@iscekic iscekic self-assigned this Jul 28, 2026
@kilo-code-bot

kilo-code-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Since the last review, only two new workflow-learning markdown files were added (E2E slot ownership and iOS simulator location-fix notes); the previously reviewed production files (appsflyer.ts/.test.ts, identity-step.tsx/.test.tsx, vitest.pure.config.ts) are unchanged, and the new docs contain no code or actionable issues.

Files Reviewed (2 new files)
  • .kilo_workflow/learnings/e2e-slot-owner-must-be-dedicated-session.md
  • .kilo_workflow/learnings/ios-simulator-cannot-starve-location-fix.md
Previous Review Summary (commit c0ce401)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit c0ce401)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the three production callback/catch-block removals (appsflyer.ts, identity-step.tsx) plus their tests and the vitest include addition; all changes are scoped, consistent with the stated intent (drop non-actionable Sentry reports), and retain the actionable reporting paths (initSdk error, purchase-connector error, validateWeatherLocation capture) with no logic, security, or test-correctness issues found.

Files Reviewed (6 files)
  • .kilo_workflow/learnings/vitest-mobile-project-includes-skip-new-tests.md
  • apps/mobile/src/lib/appsflyer.ts
  • apps/mobile/src/lib/appsflyer.test.ts
  • apps/mobile/src/components/kiloclaw/onboarding/identity-step.tsx
  • apps/mobile/src/components/kiloclaw/onboarding/identity-step.test.tsx
  • apps/mobile/vitest.pure.config.ts

Reviewed by claude-sonnet-5 · Input: 32 · Output: 7.4K · Cached: 832.1K

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added the human-ready The PR is ready for human review. label Jul 28, 2026
@iscekic
iscekic requested a review from pandemicsyn July 29, 2026 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant