Skip to content

fix(auth): surface meaningful error messages and capture root errors in Sentry#2469

Merged
mikib0 merged 8 commits into
developmentfrom
fix/auth-error-quality
May 24, 2026
Merged

fix(auth): surface meaningful error messages and capture root errors in Sentry#2469
mikib0 merged 8 commits into
developmentfrom
fix/auth-error-quality

Conversation

@mikib0

@mikib0 mikib0 commented May 21, 2026

Copy link
Copy Markdown
Collaborator

Problem

Better Auth client errors were wrapped in new Error(error.message ?? fallback) before being thrown and captured. This caused two issues:

  1. Sentry got synthetic errors: A brand-new Error was created with just the message string, losing the HTTP status code, Better Auth error code, and any original stack context. In forgotPassword / resetPassword / verifyEmail / resendVerificationEmail, two separate new Error() objects were even created — one captured, one thrown.

  2. Users saw unhelpful messages: On a 500, they'd see "Sign up failed" or the server's raw internal message. On USER_ALREADY_EXISTS, they'd see whatever the server returned rather than clear, actionable copy.

Solution

features/auth/lib/authErrors.ts (new)

Introduces AuthClientError (extends Error, carries status and code) and toAuthError(source, fallback):

  • Maps known Better Auth error codes to user-friendly copy:
    • USER_ALREADY_EXISTS → "An account with this email already exists. Try signing in instead."
    • INVALID_EMAIL_OR_PASSWORD / INVALID_PASSWORD / USER_NOT_FOUND → "Invalid email or password." (security-neutral)
    • INVALID_TOKEN / EXPIRED_TOKEN → "This link has expired or is invalid. Please request a new one."
    • TOO_MANY_REQUESTS → "Too many attempts. Please wait a moment and try again."
    • etc.
  • Falls back to a generic "Something went wrong on our end. Please try again in a moment." for 5xx responses instead of leaking internal messages
  • Passes through the server message for other 4xx responses

features/auth/hooks/useAuthActions.ts

  • All throw new Error(error.message ?? fallback) replaced with throw toAuthError(error, fallback)
  • Fixed the double-new Error antipattern: forgotPassword, resetPassword, verifyEmail, resendVerificationEmail now create a single AuthClientError, capture it, and throw it
  • Every captureException call now includes httpStatus and errorCode in extra so Sentry has the full original HTTP context

Test plan

  • Sign up with an existing email → alert shows "An account with this email already exists. Try signing in instead."
  • Sign in with wrong password → alert shows "Invalid email or password."
  • Sign in / sign up when the server is down → alert shows the generic "Something went wrong on our end" message (not a raw 500 body)
  • Forgot password / reset password / verify email with an expired token → "This link has expired or is invalid."
  • Check Sentry: errors from auth flows now include httpStatus and errorCode tags in the extras, and the AuthClientError name appears in the issue title

Summary by CodeRabbit

Release Notes

  • Chores
    • Integrated comprehensive error monitoring and diagnostics across the application to improve stability, track issues more effectively, and enable faster problem resolution for users experiencing unexpected errors.

Review Change Stack

claude and others added 2 commits May 21, 2026 08:44
API (@packrat/api):
- Add @sentry/cloudflare dependency and wrap the Worker fetch/queue
  handlers with withSentry for per-request scope isolation
- New packages/api/src/utils/sentry.ts with captureApiException,
  apiAddBreadcrumb, setApiUser, clearApiUser helpers
- Global onError handler captures all non-validation, non-404 errors
  with method/path/error_code tags; queue handler wraps processQueueBatch
  and handleEmbeddingsBatch with capture + rethrow
- Auth middleware sets Sentry user context (id, email, role) after every
  successful session resolve; breadcrumbs on unauthenticated / forbidden
  rejections; captureException on getSession failures
- weather routes: captureApiException in every catch block with
  operation name, userId, weather_operation tag, and relevant extras
- chat route: captures missing AI provider config; breadcrumb before
  stream starts with contextType/packId/messageCount; captures streamText
  onError with provider + context tags
- weatherService: captures HTTP error responses with http_status tag

Expo (apps/expo):
- _layout.tsx: add tracesSampleRate 0.2, sendDefaultPii false,
  environment tag, beforeBreadcrumb filter to strip /api/auth/ URLs;
  setUser with id/email/username on startup
- ErrorBoundary: withScope in onError adds error_source tag and
  componentStack + errorName/errorMessage as Sentry extras before capture
- useAuthActions: Sentry.addBreadcrumb for every auth flow step (sign-in
  attempt/success, Google/Apple/email, sign-up, sign-out, password reset,
  email verify); captureException in every catch with auth_method and
  auth_action tags; setUser after successful sign-in; setUser(null) on
  sign-out and account deletion
- useAuthInit: setUser after background session refresh; breadcrumbs for
  session expiry and definitive auth failures; setUser(null) on clear;
  captureException for startup auth failures

https://claude.ai/code/session_01HCrFacYwgoJ4xLTqu21gWb
…in Sentry

Previously, Better Auth client error responses were wrapped in `new Error(error.message ?? fallback)` before being thrown and/or passed to Sentry. This had two problems:
1. Sentry received a synthetic error with no status code, error code, or original context.
2. Users saw either the server's raw message or a generic fallback with no actionable detail.

Introduce `AuthClientError` and `toAuthError` (features/auth/lib/authErrors.ts) which:
- Converts a Better Auth error object into a proper JS Error carrying `status` and `code`
- Maps known Better Auth error codes (USER_ALREADY_EXISTS, INVALID_EMAIL_OR_PASSWORD, etc.) to clear user-facing copy
- Falls back to a generic "something went wrong" for 5xx responses instead of leaking internal messages

Update `useAuthActions` throughout:
- Replace every `throw new Error(error.message ?? fallback)` with `toAuthError`
- Fix the double-`new Error` antipattern in forgotPassword/resetPassword/verifyEmail/resendVerificationEmail where two separate error objects were created (one captured, one thrown)
- Thread `httpStatus` and `errorCode` through every `captureException` extra so Sentry has the original HTTP context
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@mikib0, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 33 minutes and 13 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 0c59adf9-39d5-455e-9b74-67e475c7e7c6

📥 Commits

Reviewing files that changed from the base of the PR and between 4732697 and 9011856.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock, !bun.lock
📒 Files selected for processing (18)
  • .github/agents/kieran-typescript-reviewer.agent.md
  • apps/expo/app/_layout.tsx
  • apps/expo/components/initial/ErrorBoundary.tsx
  • apps/expo/eas.json
  • apps/expo/features/ai/lib/localModelManager.ts
  • apps/expo/features/auth/hooks/useAuthActions.ts
  • apps/expo/features/auth/lib/authErrors.ts
  • apps/expo/providers/TanstackProvider.tsx
  • packages/api/package.json
  • packages/api/src/index.ts
  • packages/api/src/middleware/auth.ts
  • packages/api/src/routes/chat.ts
  • packages/api/src/routes/packs/index.ts
  • packages/api/src/routes/trailConditions/reports.ts
  • packages/api/src/routes/trails/index.ts
  • packages/api/src/routes/weather.ts
  • packages/api/src/services/weatherService.ts
  • packages/api/src/utils/sentry.ts

Walkthrough

This PR comprehensively integrates Sentry monitoring across the PackRat client and API. It introduces centralized error utilities, standardizes auth error handling, and instruments routes/services with structured exception reporting, breadcrumbs, and user context tracking.

Changes

Sentry Monitoring Integration

Layer / File(s) Summary
Sentry Instrumentation Policy and Guidance
.github/agents/kieran-typescript-reviewer.agent.md, CLAUDE.md, copilot-instructions.md
Documentation updated with required Sentry practices: breadcrumb placement, exception capture in catch blocks, toAuthError conversion for auth failures, HTTP status/error codes in extras, and platform-specific helper usage (@sentry/react-native for Expo, @packrat/api/utils/sentry for API).
Expo App Configuration and Sentry Initialization
apps/expo/app.config.ts, apps/expo/eas.json, apps/expo/app/_layout.tsx
App variant (development, preview, production) configured via APP_VARIANT env and wired into EAS profiles. Sentry initialized with sendDefaultPii: false, environment from appVariant, breadcrumb filtering to drop /api/auth/ URLs, and shaped user identity (id/email/derived username).
Expo Error Boundaries and Lifecycle Instrumentation
apps/expo/components/initial/ErrorBoundary.tsx, apps/expo/features/ai/lib/localModelManager.ts, apps/expo/providers/TanstackProvider.tsx
Error boundary wraps Sentry capture in scopes with error_source tag and component stack extras. Local model manager emits breadcrumbs for download/preparation lifecycle and captures HTTP/unexpected errors. React Query cache handlers selectively report errors (excluding 401/429/404) with operation tags.
Standardized Auth Error Handling
apps/expo/features/auth/lib/authErrors.ts
BetterAuthError type carries HTTP status and error code. AuthClientError class extends Error with attached status/code. toAuthError converts raw failures using mapped code messages, 5xx fallback, server message, or provided fallback.
Expo Auth Actions and Session Management with Sentry
apps/expo/features/auth/hooks/useAuthActions.ts, apps/expo/features/auth/hooks/useAuthInit.ts
All auth flows (sign-in, sign-up, sign-out, password reset, verification, account deletion) emit breadcrumbs for flow milestones. Failures converted via toAuthError and captured to Sentry with auth_method/auth_action tags plus HTTP status/code metadata. Session apply/logout syncs/clears Sentry user identity.
API Sentry Infrastructure and Utilities
packages/api/src/utils/sentry.ts, packages/api/package.json, packages/api/src/utils/env-validation.ts
New sentry.ts module exports captureApiException (enriches scope, captures, logs), apiAddBreadcrumb (structured breadcrumbs), setApiUser/clearApiUser (user context). @sentry/cloudflare dependency added. SENTRY_RELEASE env var support.
API Worker Sentry Wrapping and Auth Middleware
packages/api/src/index.ts, packages/api/src/middleware/auth.ts
Worker wrapped with withSentry for DSN/environment/tracing. .onError handler conditionally captures unexpected errors (excluding validation/parse/not-found) with method/path tags. Queue processing wrapped in try/catch with Sentry reporting. Auth plugins wrap auth.api.getSession calls, add breadcrumbs for access decisions, and call setApiUser to attach user context.
API Routes Error Instrumentation
packages/api/src/routes/chat.ts, packages/api/src/routes/packs/index.ts, packages/api/src/routes/trailConditions/reports.ts, packages/api/src/routes/trails/index.ts, packages/api/src/routes/user/index.ts, packages/api/src/routes/weather.ts, packages/api/src/routes/wildlife/index.ts, packages/api/src/services/weatherService.ts
Routes replace console.error with captureApiException calls that include operation names, user context, feature tags, and route-specific extras (query params, IDs, validation paths). HTTP error messages standardized (e.g., WeatherAPI HTTP <status>). Breadcrumbs added for significant operations (e.g., chat stream start, weather forecast).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PackRat-AI/PackRat#2378: Instruments packages/api/src/services/weatherService.ts to capture Sentry reports for weather API failures.
  • PackRat-AI/PackRat#2373: Refactors authentication flow in same files (useAuthActions.ts, useAuthInit.ts, packages/api/src/middleware/auth.ts) in a Better Auth/OAuth migration context.
  • PackRat-AI/PackRat#2462: Overlaps on packages/api/src/index.ts worker export wrapping with withSentry(...) and Sentry error handling in runtime handlers.

Suggested labels

api, mobile, documentation

Suggested reviewers

  • andrew-bierman
  • Isthisanmol
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: introducing meaningful error messages and Sentry error capture in auth flows via AuthClientError and toAuthError.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/auth-error-quality

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…structions

Add a "Monitoring (Sentry)" section to CLAUDE.md and copilot-instructions.md covering:
- Use addBreadcrumb before async operations
- captureException in every catch block with tags and extra context
- Never re-wrap the root error in new Error() before capturing — loses stack/status/code
- Better Auth errors: use toAuthError from authErrors.ts to produce a single AuthClientError
  (one object to capture and throw, not two separate synthetic errors)
- Include httpStatus and errorCode in extra for all HTTP errors
- API side: use captureApiException from @packrat/api/utils/sentry

Also adds a §10 "Sentry Instrumentation" check to the kieran-typescript-reviewer agent
with concrete pass/fail examples so code reviews catch missing or broken capture patterns.
@mikib0 mikib0 changed the base branch from main to development May 21, 2026 13:24
@mikib0 mikib0 requested a review from Copilot May 21, 2026 13:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves Sentry observability and user-facing auth errors by preserving root error context (status/code) and adding consistent instrumentation across the Expo app and the Cloudflare Workers API.

Changes:

  • Added an Expo AuthClientError + toAuthError mapper to surface user-friendly auth messages while keeping HTTP status/error codes for Sentry context.
  • Introduced API-side Sentry helpers and initialized Sentry in the Worker entrypoint; added structured captureApiException usage across middleware/routes/services.
  • Updated Sentry initialization/user identification and added breadcrumbs/captures across key auth flows and error boundaries; documented the new monitoring conventions.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/api/src/utils/sentry.ts New API Sentry helper utilities (captureApiException, breadcrumbs, user helpers).
packages/api/src/services/weatherService.ts Captures and rethrows structured weather API failures.
packages/api/src/routes/weather.ts Adds Sentry capture in weather endpoints and schema-validation error reporting.
packages/api/src/routes/chat.ts Adds breadcrumbs and structured captures around AI chat streaming errors.
packages/api/src/middleware/auth.ts Captures Better Auth session retrieval failures; sets Sentry user context per request.
packages/api/src/index.ts Wraps Worker handler with withSentry; captures unexpected Elysia errors and queue handler failures.
packages/api/package.json Adds @sentry/cloudflare dependency.
apps/expo/features/auth/lib/authErrors.ts New Better Auth error → user-friendly message mapping (AuthClientError, toAuthError).
apps/expo/features/auth/hooks/useAuthInit.ts Syncs Sentry user identity with session lifecycle and captures init failures.
apps/expo/features/auth/hooks/useAuthActions.ts Uses toAuthError, adds breadcrumbs, and captures auth flow failures with status/code extras.
apps/expo/components/initial/ErrorBoundary.tsx Adds Sentry capture and componentStack context in the app error boundary.
apps/expo/app/_layout.tsx Updates Sentry init config, breadcrumb filtering, and sets initial Sentry user identity.
copilot-instructions.md Documents required Sentry instrumentation patterns for Expo and API code.
CLAUDE.md Documents required Sentry instrumentation patterns for Expo and API code.
.github/agents/kieran-typescript-reviewer.agent.md Adds Sentry instrumentation guidance to the reviewer agent instructions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/api/src/index.ts
Comment on lines +50 to +55
.onError(({ error, code, request }) => {
console.error('Error occurred:', error);

// Only report unexpected server errors — not user-input or routing errors.
if (code !== 'VALIDATION' && code !== 'PARSE' && code !== 'NOT_FOUND') {
captureApiException(error, {
Comment thread packages/api/src/utils/sentry.ts Outdated

withScope((scope) => {
scope.setTag('operation', operation);
if (userId) scope.setUser({ id: userId });
Comment thread packages/api/src/routes/weather.ts Outdated
tags: { weather_operation: 'forecast', error_type: 'schema_validation' },
extra: { locationId: id, invalidPaths },
});
throw new Error(`Weather forecast response failed schema validation at: ${invalidPaths}`);
Comment on lines +56 to +66
// Attach the component stack as extra context so Sentry shows exactly
// which component tree caused the crash.
Sentry.withScope((scope) => {
scope.setTag('error_source', 'error_boundary');
scope.setExtra('componentStack', info.componentStack);
if (error instanceof Error) {
scope.setExtra('errorName', error.name);
scope.setExtra('errorMessage', error.message);
}
Sentry.captureException(error);
});
Comment thread apps/expo/app/_layout.tsx Outdated
Comment on lines +42 to +50
// Sync the authenticated user to Sentry on startup so every event is
// associated with the correct user identity.
const user = userStore.peek();
if (user) {
Sentry.setUser(user);
Sentry.setUser({
id: user.id,
email: user.email,
username: `${user.firstName} ${user.lastName}`.trim(),
});
Comment on lines +85 to +90
Sentry.addBreadcrumb({
category: 'auth',
message: 'Email sign in attempt',
level: 'info',
data: { email },
});
Comment on lines +16 to +19
TOO_MANY_REQUESTS: 'Too many attempts. Please wait a moment and try again.',
INVALID_TOKEN: 'This link has expired or is invalid. Please request a new one.',
EXPIRED_TOKEN: 'This link has expired. Please request a new one.',
PASSWORD_TOO_SHORT: 'Password is too short.',
Comment thread packages/api/src/index.ts
Comment on lines +19 to 21
import { captureApiException } from '@packrat/api/utils/sentry';
import { withSentry } from '@sentry/cloudflare';
import { Elysia } from 'elysia';
mikib0 added 3 commits May 23, 2026 14:52
…obal handler, align route catches

- localModelManager: capture download failures (HTTP status + network) and
  _prepareLlamaModel errors with device OS/version context; add breadcrumbs
  before each operation so the event trail is visible in Sentry
- _layout.tsx + eas.json + app.config.ts: read APP_VARIANT from
  Constants.expoConfig.extra instead of NODE_ENV so development/preview
  EAS builds no longer report as environment:'production' in Sentry
- TanstackProvider: wire QueryCache + MutationCache global onError handlers
  with 401/429/404 noise filter; every future hook gets coverage for free
- trails, trailConditions, wildlife, packs, user: add captureApiException to
  catch blocks that were swallowing errors before the global handler; user
  routes capture then rethrow for double-context; trails skips intentional 503
@coderabbitai

coderabbitai Bot commented May 23, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{"name":"HttpError","status":401,"request":{"method":"PATCH","url":"https://api.github.com/repos/PackRat-AI/PackRat/issues/comments/4506628999","headers":{"accept":"application/vnd.github.v3+json","user-agent":"octokit.js/0.0.0-development octokit-core.js/7.0.6 Node.js/24","authorization":"token [REDACTED]","content-type":"application/json; charset=utf-8"},"body":{"body":"<!-- This is an auto-generated comment: summarize by coderabbit.ai -->\n<!-- This is an auto-generated comment: review in progress by coderabbit.ai -->\n\n> [!NOTE]\n> Currently processing new changes in this PR. This may take a few minutes, please wait...\n> \n> <details>\n> <summary>⚙️ Run configuration</summary>\n> \n> **Configuration used**: Path: .coderabbit.yaml\n> \n> **Review profile**: ASSERTIVE\n> \n> **Plan**: Pro\n> \n> **Run ID**: `d39b8eb8-eb1f-4ef7-9bf6-d13e148644c2`\n> \n> </details>\n> \n> <details>\n> <summary>📥 Commits</summary>\n> \n> Reviewing files that changed from the base of the PR and between 9e8be8bde72a2d5fd2dc72fb8e88646455c3a54c and 47326977f69116b5cdeda01df38963dd6b5a9286.\n> \n> </details>\n> \n> <details>\n> <summary>📒 Files selected for processing (25)</summary>\n> \n> * `.github/agents/kieran-typescript-reviewer.agent.md`\n> * `CLAUDE.md`\n> * `apps/expo/app.config.ts`\n> * `apps/expo/app/_layout.tsx`\n> * `apps/expo/components/initial/ErrorBoundary.tsx`\n> * `apps/expo/eas.json`\n> * `apps/expo/features/ai/lib/localModelManager.ts`\n> * `apps/expo/features/auth/hooks/useAuthActions.ts`\n> * `apps/expo/features/auth/hooks/useAuthInit.ts`\n> * `apps/expo/features/auth/lib/authErrors.ts`\n> * `apps/expo/providers/TanstackProvider.tsx`\n> * `copilot-instructions.md`\n> * `packages/api/package.json`\n> * `packages/api/src/index.ts`\n> * `packages/api/src/middleware/auth.ts`\n> * `packages/api/src/routes/chat.ts`\n> * `packages/api/src/routes/packs/index.ts`\n> * `packages/api/src/routes/trailConditions/reports.ts`\n> * `packages/api/src/routes/trails/index.ts`\n> * `packages/api/src/routes/user/index.ts`\n> * `packages/api/src/routes/weather.ts`\n> * `packages/api/src/routes/wildlife/index.ts`\n> * `packages/api/src/services/weatherService.ts`\n> * `packages/api/src/utils/env-validation.ts`\n> * `packages/api/src/utils/sentry.ts`\n> \n> </details>\n> \n> ```ascii\n>  _______________________________________\n> < We're gonna need a bigger bug zapper. >\n>  ---------------------------------------\n>   \\\n>    \\   (\\__/)\n>        (•ㅅ•)\n>        /   づ\n> ```\n\n<!-- end of auto-generated comment: review in progress by coderabbit.ai -->\n\n<!-- finishing_touch_checkbox_start -->\n\n<details>\n<summary>✨ Finishing Touches</summary>\n\n<details>\n<summary>📝 Generate docstrings</summary>\n\n- [ ] <!-- {\"checkboxId\": \"7962f53c-55bc-4827-bfbf-6a18da830691\"} --> Create stacked PR\n- [ ] <!-- {\"checkboxId\": \"3e1879ae-f29b-4d0d-8e06-d12b7ba33d98\"} --> Commit on current branch\n\n</details>\n<details>\n<summary>🧪 Generate unit tests (beta)</summary>\n\n- [ ] <!-- {\"checkboxId\": \"f47ac10b-58cc-4372-a567-0e02b2c3d479\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Create PR with unit tests\n- [ ] <!-- {\"checkboxId\": \"6ba7b810-9dad-11d1-80b4-00c04fd430c8\", \"radioGroupId\": \"utg-output-choice-group-unknown_comment_id\"} -->   Commit unit tests in branch `fix/auth-error-quality`\n\n</details>\n\n</details>\n\n<!-- finishing_touch_checkbox_end -->\n<!-- tips_start -->\n\n---\n\nThanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=PackRat-AI/PackRat&utm_content=2469)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.\n\n<details>\n<summary>❤️ Share</summary>\n\n- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)\n- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)\n- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)\n- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)\n\n</details>\n\n\n<sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub>\n\n<!-- tips_end -->\n<!-- usage_tips_start -->\n\n> [!TIP]\n> <details>\n> <summary>You can generate walkthrough in a markdown collapsible section to save space.</summary>\n> \n> Enable the `reviews.collapse_walkthrough` setting to generate walkthrough in a markdown collapsible section.\n> \n> </details>\n\n<!-- usage_tips_end -->"},"request":{"signal":{}}},"response":{"url":"https://api.github.com/repos/PackRat-AI/PackRat/issues/comments/4506628999","status":401,"headers":{"access-control-allow-origin":"*","access-control-expose-headers":"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset","connection":"close","content-security-policy":"default-src 'none'","content-type":"application/json; charset=utf-8","date":"Sat, 23 May 2026 13:54:25 GMT","referrer-policy":"origin-when-cross-origin, strict-origin-when-cross-origin","server":"github.com","strict-transport-security":"max-age=31536000; includeSubdomains; preload","vary":"Accept-Encoding, Accept, X-Requested-With","x-content-type-options":"nosniff","x-frame-options":"deny","x-github-media-type":"github.v3; format=json","x-github-request-id":"8050:1AC778:CBC5AD7:3011931D:6A11B191","x-xss-protection":"0"},"data":{"message":"Bad credentials","documentation_url":"https://docs.github.com/rest","status":"401"}}}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 18

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/expo/features/auth/hooks/useAuthActions.ts (1)

111-165: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Google sign-in leaves loading state stuck on successful path.

setIsLoading(true) on Line 112 is never reverted when Google auth succeeds, so UI can remain blocked.

Suggested fix
   const signInWithGoogle = async () => {
     setIsLoading(true);
     Sentry.addBreadcrumb({ category: 'auth', message: 'Google sign in attempt', level: 'info' });
     try {
@@
     } catch (error) {
-      setIsLoading(false);
-
       if (isErrorWithCode(error) && error.code === statusCodes.SIGN_IN_CANCELLED) {
@@
       }
 
       throw error;
+    } finally {
+      setIsLoading(false);
     }
   };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/expo/features/auth/hooks/useAuthActions.ts` around lines 111 - 165, The
signInWithGoogle function sets setIsLoading(true) but never resets it on
success, leaving the UI stuck; update signInWithGoogle to always call
setIsLoading(false) after a successful sign-in (e.g., immediately after
applySession(...) and the Sentry breadcrumb) or, better, move the loading reset
into a finally block so setIsLoading(false) runs on both success and error; look
for the signInWithGoogle function and the applySession call to place the fix.
apps/expo/eas.json (1)

23-40: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix Sentry environment tagging for EAS e2e builds

apps/expo/eas.json’s build.e2e sets "environment": "preview" and "channel": "preview" but doesn’t set env.APP_VARIANT. apps/expo/app.config.ts then defaults extra.appVariant to 'production', and apps/expo/app/_layout.tsx uses that value for Sentry environment, so e2e events are tagged as production. Add env: { "APP_VARIANT": "preview" } to the e2e profile if e2e should be tagged as preview in Sentry.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/expo/eas.json` around lines 23 - 40, The e2e profile in eas.json is
missing APP_VARIANT so app.config.ts falls back to 'production' and Sentry tags
e2e builds as production; add an env entry to the e2e profile: set APP_VARIANT
to "preview" (i.e. add env: { "APP_VARIANT": "preview" } under the "e2e"
profile) so extra.appVariant in app.config.ts and the Sentry environment used in
app/_layout.tsx will be "preview".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/agents/kieran-typescript-reviewer.agent.md:
- Around line 119-134: Add missing blank lines around the fenced TypeScript code
blocks to satisfy MD031: ensure there is a blank line before each opening ```ts
fence and a blank line after each closing ``` fence in the markdown containing
the examples that call Sentry.captureException and toAuthError; verify each
fenced block starts with ```ts on its own line and ends with ``` on its own line
and that there is an empty line separating the preceding and following
paragraphs (the blocks showing the failing snippet using new Error(...) and the
passing snippet using const err = toAuthError(...)).

In `@apps/expo/app/_layout.tsx`:
- Around line 35-42: The beforeBreadcrumb filter currently drops breadcrumbs for
'/api/auth/' to avoid token leakage; instead, update
beforeBreadcrumb(breadcrumb) to scrub sensitive query parameters for all HTTP
breadcrumbs: when breadcrumb.type === 'http' and breadcrumb.data?.url is
present, parse the URL (using URL or a safe parser), remove or redact query keys
in a denylist (e.g., token, access_token, auth, password, jwt, session), rebuild
the URL without those params and assign it back to breadcrumb.data.url (or
replace values with '[REDACTED]'), and then return breadcrumb; keep the existing
special-case behavior (if you still want to drop some endpoints) but prefer
sanitization over dropping so other breadcrumbs are preserved.
- Around line 45-54: The module-level call that captures userStore.peek() and
immediately calls Sentry.setUser should be removed and replaced with a useEffect
that waits for userSyncState.isPersistLoaded (or simply rely on the existing
useAuthInit/applySessionUser path); specifically, stop using userStore.peek() at
module evaluation in apps/expo/app/_layout.tsx and instead in your component
useEffect watch userSyncState.isPersistLoaded and then call Sentry.setUser with
the hydrated user (id, email, username) — or remove the module-scope
Sentry.setUser entirely so applySessionUser (invoked by useAuthInit) is the
single place that sets the Sentry user.

In `@apps/expo/components/initial/ErrorBoundary.tsx`:
- Around line 56-66: The code is adding redundant extras for errorName and
errorMessage inside Sentry.withScope; remove the two scope.setExtra calls that
set 'errorName' and 'errorMessage' and keep the component stack and tag logic
intact so Sentry.captureException(error) still receives the Error instance
(refer to Sentry.withScope, scope.setExtra('componentStack',
info.componentStack), the two scope.setExtra('errorName'...) /
scope.setExtra('errorMessage'...) calls to remove, and
Sentry.captureException(error) to leave in place).

In `@apps/expo/features/auth/hooks/useAuthActions.ts`:
- Around line 85-90: Sentry.addBreadcrumb calls in useAuthActions.ts are sending
plaintext emails (PII); change those to send a non-identifying representation
instead (e.g., emailDomain or a hashed/redacted value) by creating a small
helper (e.g., redactEmail or hashEmail) and use it wherever Sentry.addBreadcrumb
or Sentry.setExtra is called in this file; update the breadcrumb data from {
email } to something like { emailDomain: redactEmail(email) } or { emailHash:
hashEmail(email) } and apply the same pattern to all other auth
breadcrumbs/extras in useAuthActions.ts so no raw email is sent to telemetry.
- Around line 261-263: In the catch block inside useAuthActions.ts where
Sentry.captureException(error, { tags: { auth_action: 'sign_out' } }) is called,
augment the Sentry call to include HTTP context: detect if error is an HTTP
error (e.g., has response/status or errorCode), extract httpStatus and
errorCode, and pass them in the Sentry payload under extra (e.g., extra: {
httpStatus, errorCode }) while keeping the existing tags; update the
Sentry.captureException invocation in the sign-out error handler to include
these fields so HTTP failures are searchable.

In `@apps/expo/providers/TanstackProvider.tsx`:
- Around line 7-10: Refactor the current shouldCapture function so callers can
access the extracted HTTP metadata: either change shouldCapture(error) to return
an object like {capture: boolean, httpStatus?: number, errorCode?: string} or
move the status/errorCode extraction into the Sentry handlers and use the same
filter logic there; ensure the symbols mentioned (shouldCapture and the Sentry
capture handlers where Sentry.captureException is called) include httpStatus and
errorCode in the Sentry extra payload for HTTP errors and preserve the existing
filter behavior (do not capture when status is 401, 429, or 404).
- Around line 15-21: The Sentry capture in the onError handler should include
HTTP metadata: extract the HTTP status from error.status or error.httpStatus and
the error code from error.code or error.errorCode (fall back to undefined if
missing) and add them to the Sentry.extra object alongside query.queryKey;
update the onError function (and keep shouldCapture logic) so
Sentry.captureException(error, { tags: {...}, extra: { queryKey: query.queryKey,
httpStatus, errorCode } }) is called with those extracted fields.
- Around line 24-28: The Sentry call in the onError handler should include
httpStatus and errorCode in the extra payload for HTTP errors; update the
onError implementation (the shouldCapture check and Sentry.captureException
call) to extract httpStatus (e.g., from error.response?.status or error.status)
and errorCode (e.g., from error.code or error.errorCode) and pass them inside
the extra object when calling Sentry.captureException alongside the existing
tags so HTTP errors become searchable.

In `@packages/api/src/index.ts`:
- Around line 55-63: The Sentry payload sent by captureApiException in the
elysia.onError path is missing httpStatus in the extra metadata; update the call
to captureApiException to include httpStatus (use the existing code variable
that represents the HTTP status) inside the extra object so extra contains both
errorCode and httpStatus, ensuring searchable HTTP error metadata.

In `@packages/api/src/middleware/auth.ts`:
- Around line 31-35: The Sentry capture calls in the auth middleware (e.g., the
captureApiException call around operation 'auth.getSession' and the similar
catch at lines ~77-82) must include extra fields for httpStatus and errorCode so
outages are searchable; update the captureApiException invocations (for
operation 'auth.getSession' and the other auth operation) to pass an extra
object like extra: { httpStatus: 500, errorCode: '<unique_error_code>' } (choose
a clear code such as 'auth.getSession' or 'auth.<operationName>') alongside
existing operation/tags so the 500 captures include both httpStatus and
errorCode.

In `@packages/api/src/routes/chat.ts`:
- Around line 97-102: The Sentry capture in the chat.stream branch is missing
HTTP metadata; update the captureApiException call (the one creating new
Error('AI provider not configured')) to include extra.httpStatus: 500 and
extra.errorCode: something descriptive (e.g., 'AI_PROVIDER_NOT_CONFIGURED'),
keeping the existing operation: 'chat.stream', userId and tags: { ai_provider:
AI_PROVIDER } so the error becomes searchable by HTTP status and code.

In `@packages/api/src/routes/packs/index.ts`:
- Around line 208-211: Several captureApiException calls in this file (e.g., the
one with operation 'packs.analyzeImage' and the other 500-path catches) are
missing required httpStatus and errorCode fields in the extra payload; update
every captureApiException(...) used in these catch blocks to include httpStatus
(e.g., error?.status || 500) and errorCode (e.g., error?.code ||
'internal_server_error') in the second-argument object alongside operation and
tags so Sentry captures both values for searchability; locate all calls to
captureApiException in this file (including the ones mentioned around the other
catches) and add these two keys to the extra payload.
- Around line 212-217: Replace the response that includes error.message with a
generic 500 message: in the packs route where you call status(500, { error:
error instanceof Error ? `Failed to analyze image: ${error.message}` : 'Failed
to analyze image' }), remove echoing error.message and always return a
non-sensitive string like 'Failed to analyze image'; continue to capture the
original error with your existing Sentry/telemetry call (or add
Sentry.captureException(error) nearby) so internals stay logged but not leaked
to clients.

In `@packages/api/src/routes/trailConditions/reports.ts`:
- Around line 65-69: The Sentry captures via captureApiException currently lack
searchable HTTP metadata; update each captureApiException call in this file
(e.g., the one with operation 'trailConditions.list' and the other occurrences
around the ranges noted) to add extra.httpStatus: 500 and extra.errorCode:
'INTERNAL_SERVER_ERROR' (or the appropriate error code used by the project) so
that the extra object includes { trailName, limit, httpStatus: 500, errorCode:
'INTERNAL_SERVER_ERROR' }; apply the same change to the other
captureApiException calls referenced (around lines 130-134, 171-175, 230-234,
271-275) ensuring the extras are consistently named for searchability.

In `@packages/api/src/routes/trails/index.ts`:
- Around line 93-97: The Sentry captures calling captureApiException in the
trails route need to include searchable fields; update the captureApiException
calls (e.g., the one with operation 'trails.search' and the similar captures
later) to add httpStatus and a route-specific errorCode into the extra object
(for example extra: { q, lat, lon, radius, sport, httpStatus: 500, errorCode:
'TRAILS_SEARCH_ERROR' }); ensure each distinct catch uses an appropriate
httpStatus and a unique errorCode (e.g., TRAILS_SEARCH_ERROR,
TRAILS_LOOKUP_ERROR, TRAILS_CREATE_ERROR) when modifying the extra payload
passed to captureApiException.

In `@packages/api/src/routes/weather.ts`:
- Around line 48-53: The Sentry captures using captureApiException in the
weather route handlers (e.g., the block with operation 'weather.search' that
logs user?.userId and extra: { query: q }) must include httpStatus and errorCode
in the extra payload; update the extra object to add httpStatus (the HTTP status
returned by WeatherAPI or your response) and errorCode (the route-level error
code constant you define/use for weather errors). Apply the same change to the
other captureApiException calls in this file that handle HTTP errors (the
similar blocks around the other weather handlers) so every HTTP error capture
includes extra: { query, httpStatus, errorCode } (and keep existing tags/userId
fields).

In `@packages/api/src/services/weatherService.ts`:
- Around line 37-41: The Sentry capture call in
weatherService.getWeatherForLocation currently puts the HTTP status in tags;
change it so captureApiException includes httpStatus and errorCode inside the
extra object (e.g., extra: { location, apiMessage, httpStatus:
String(response.status), errorCode: 'OPENWEATHERMAP_HTTP_ERROR' }) and remove
the http status from tags; update the captureApiException invocation accordingly
to ensure httpStatus and errorCode are present and searchable.

---

Outside diff comments:
In `@apps/expo/eas.json`:
- Around line 23-40: The e2e profile in eas.json is missing APP_VARIANT so
app.config.ts falls back to 'production' and Sentry tags e2e builds as
production; add an env entry to the e2e profile: set APP_VARIANT to "preview"
(i.e. add env: { "APP_VARIANT": "preview" } under the "e2e" profile) so
extra.appVariant in app.config.ts and the Sentry environment used in
app/_layout.tsx will be "preview".

In `@apps/expo/features/auth/hooks/useAuthActions.ts`:
- Around line 111-165: The signInWithGoogle function sets setIsLoading(true) but
never resets it on success, leaving the UI stuck; update signInWithGoogle to
always call setIsLoading(false) after a successful sign-in (e.g., immediately
after applySession(...) and the Sentry breadcrumb) or, better, move the loading
reset into a finally block so setIsLoading(false) runs on both success and
error; look for the signInWithGoogle function and the applySession call to place
the fix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d39b8eb8-eb1f-4ef7-9bf6-d13e148644c2

📥 Commits

Reviewing files that changed from the base of the PR and between 9e8be8b and 4732697.

📒 Files selected for processing (25)
  • .github/agents/kieran-typescript-reviewer.agent.md
  • CLAUDE.md
  • apps/expo/app.config.ts
  • apps/expo/app/_layout.tsx
  • apps/expo/components/initial/ErrorBoundary.tsx
  • apps/expo/eas.json
  • apps/expo/features/ai/lib/localModelManager.ts
  • apps/expo/features/auth/hooks/useAuthActions.ts
  • apps/expo/features/auth/hooks/useAuthInit.ts
  • apps/expo/features/auth/lib/authErrors.ts
  • apps/expo/providers/TanstackProvider.tsx
  • copilot-instructions.md
  • packages/api/package.json
  • packages/api/src/index.ts
  • packages/api/src/middleware/auth.ts
  • packages/api/src/routes/chat.ts
  • packages/api/src/routes/packs/index.ts
  • packages/api/src/routes/trailConditions/reports.ts
  • packages/api/src/routes/trails/index.ts
  • packages/api/src/routes/user/index.ts
  • packages/api/src/routes/weather.ts
  • packages/api/src/routes/wildlife/index.ts
  • packages/api/src/services/weatherService.ts
  • packages/api/src/utils/env-validation.ts
  • packages/api/src/utils/sentry.ts

Comment thread .github/agents/kieran-typescript-reviewer.agent.md
Comment thread apps/expo/app/_layout.tsx
Comment thread apps/expo/app/_layout.tsx Outdated
Comment thread apps/expo/components/initial/ErrorBoundary.tsx Outdated
Comment thread apps/expo/features/auth/hooks/useAuthActions.ts
Comment thread packages/api/src/routes/packs/index.ts Outdated
Comment thread packages/api/src/routes/trailConditions/reports.ts
Comment thread packages/api/src/routes/trails/index.ts
Comment thread packages/api/src/routes/weather.ts
Comment thread packages/api/src/services/weatherService.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 5 comments.

Comment on lines +33 to +35
scope.setTag('operation', operation);
if (userId) scope.setUser({ id: userId });
if (tags) {
Comment thread packages/api/src/index.ts
Comment on lines +50 to 66
.onError(({ error, code, request }) => {
console.error('Error occurred:', error);

// Only report unexpected server errors — not user-input or routing errors.
if (code !== 'VALIDATION' && code !== 'PARSE' && code !== 'NOT_FOUND') {
captureApiException(error, {
operation: 'elysia.onError',
tags: {
error_code: code,
method: request?.method ?? 'UNKNOWN',
path: request ? new URL(request.url).pathname : 'UNKNOWN',
},
extra: { errorCode: code },
});
}

if (code === 'VALIDATION' || code === 'PARSE') {
Comment thread packages/api/src/routes/weather.ts Outdated
Comment on lines 173 to 177
userId: user?.userId,
tags: { weather_operation: 'forecast', error_type: 'schema_validation' },
extra: { locationId: id, invalidPaths },
});
throw new Error(`Weather forecast response failed schema validation at: ${invalidPaths}`);
Comment on lines +56 to +66
// Attach the component stack as extra context so Sentry shows exactly
// which component tree caused the crash.
Sentry.withScope((scope) => {
scope.setTag('error_source', 'error_boundary');
scope.setExtra('componentStack', info.componentStack);
if (error instanceof Error) {
scope.setExtra('errorName', error.name);
scope.setExtra('errorMessage', error.message);
}
Sentry.captureException(error);
});
Comment on lines +85 to +90
Sentry.addBreadcrumb({
category: 'auth',
message: 'Email sign in attempt',
level: 'info',
data: { email },
});
mikib0 added 2 commits May 24, 2026 15:17
- signInWithGoogle: move setIsLoading(false) to finally block so loading
  state always resets, even on successful sign-in
- Redact raw email from Sentry breadcrumbs and extra (use emailDomain) to
  reduce PII exposure while keeping auth flow context
- Add httpStatus/errorCode to sign-out, query/mutation cache, auth
  middleware, chat, packs, trailConditions, trails, weather Sentry captures
  so HTTP errors are searchable in Sentry
- authErrors: align EXPIRED_TOKEN message with INVALID_TOKEN for consistent
  security-neutral copy
- eas.json: add APP_VARIANT=preview to e2e profile so Sentry tags e2e builds
  as preview instead of falling back to production
- _layout.tsx: replace auth-URL breadcrumb drop with URL param scrubbing for
  all HTTP breadcrumbs; remove module-level Sentry.setUser race (rely on
  applySession in useAuthActions)
- ErrorBoundary: use beforeCapture to set error_source tag instead of
  manually calling captureException inside onError (avoids duplicate events);
  drop redundant errorName/errorMessage extras
- sentry.ts: tag userId instead of calling setUser to avoid overwriting
  richer user context already set by setApiUser
- index.ts: remove duplicate console.error (captureApiException already
  logs); coerce Elysia error code to string to fix TS2322
- weather.ts: return 500 response after capturing ZodError instead of
  re-throwing a synthetic Error (prevents double-capture by global onError)
- weatherService.ts: move http_status from tags to extra as httpStatus, add
  errorCode for searchability
Conflict in localModelManager.ts: kept development's console.log and
if (!_isCancellingDownload) guard, combined with our Sentry capture so
download errors are reported to Sentry only when not user-cancelled.
@cloudflare-workers-and-pages

Copy link
Copy Markdown
Contributor

Deploying packrat-guides with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9011856
Status:⚡️  Build in progress...

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
packrat-admin 9011856 Commit Preview URL

Branch Preview URL
May 24 2026, 02:24 PM

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file api ci/cd mobile labels May 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for API Unit Tests Coverage (./packages/api)

Status Category Percentage Covered / Total
🔵 Lines 95.02% (🎯 95%) 726 / 764
🔵 Statements 95.02% (🎯 95%) 726 / 764
🔵 Functions 100% (🎯 97%) 44 / 44
🔵 Branches 95.45% (🎯 92%) 294 / 308
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/api/src/utils/sentry.ts 0% 100% 100% 0% 8-73
Generated in workflow #1452 for commit 9011856 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Expo Unit Tests Coverage (./apps/expo)

Status Category Percentage Covered / Total
🔵 Lines 97.56% (🎯 95%) 560 / 574
🔵 Statements 97.56% (🎯 95%) 560 / 574
🔵 Functions 100% (🎯 97%) 51 / 51
🔵 Branches 95% (🎯 92%) 190 / 200
File CoverageNo changed files found.
Generated in workflow #1452 for commit 9011856 by the Vitest Coverage Report Action

@cloudflare-workers-and-pages

Copy link
Copy Markdown
Contributor

Deploying packrat-landing with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9011856
Status: ✅  Deploy successful!
Preview URL: https://70aac2be.packrat-landing.pages.dev
Branch Preview URL: https://fix-auth-error-quality.packrat-landing.pages.dev

View logs

@mikib0 mikib0 merged commit 675a62d into development May 24, 2026
15 of 20 checks passed
@mikib0 mikib0 deleted the fix/auth-error-quality branch May 24, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api ci/cd dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation mobile

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants