Skip to content

Conversation

@conroy-ricketts
Copy link
Contributor

@conroy-ricketts conroy-ricketts commented Dec 2, 2025

CI-418

(this is for a mobile action item)

Product Description

I updated the user-facing error message in the event of a 403 forbidden error when tapping the refresh button for the opportunities list (and for all 403 forbidden errors for that matter).

Technical Summary

I noticed that we are already handling the forbidden error case with the correct message for the PersonalIdPhoneFragment here, so there is no need to make any specific changes for that error message in Personal ID after generalizing the default error message for all 403 forbidden errors.

Also, when I was looking at our other error messages, I noticed that we had some missing string translations. So I went ahead and added them.

Safety Assurance

Safety story

I verified this code will show an updated error message when the user taps on the refresh button and the API call fails with a 403 forbidden error by forcing it in the code.

QA Plan

For anyone that is able, we should verify that the non-English translations are correct.

Added code to handle an alternative error message for a 403 forbidden error.
@conroy-ricketts conroy-ricketts self-assigned this Dec 2, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

📝 Walkthrough

Walkthrough

Maps PersonalId API FORBIDDEN error to a new network_forbidden_error string and adds that string plus several recovery_network_* localized entries across multiple locale resource files. A minor formatting change was made in ConnectJobsListsFragment.java with no behavioral impact. No public API or exported declarations were removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Areas to check:
    • PersonalIdApiErrorHandler: confirm FORBIDDEN -> network_forbidden_error mapping and resource lookup
    • Consistency and completeness of newly added string keys across all locale files
    • Verify no accidental string-key mismatches or typos in resource names

Possibly related PRs

Suggested reviewers

  • OrangeAndGreen
  • shubham1g5
  • Jignesh-dimagi

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly and specifically summarizes the main change: updating the error message for 403 forbidden errors when refreshing opportunities, making it both concise and directly related to the changeset.
Description check ✅ Passed The PR description provides a Product Description (user-facing changes), Technical Summary (with links and context), and Safety Assurance (verification method and QA plan), covering all critical template sections appropriately.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch task/CI-418-opportunities-not-refreshing

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a81e3a5 and 34d9bc8.

📒 Files selected for processing (11)
  • app/res/values-es/strings.xml (3 hunks)
  • app/res/values-fr/strings.xml (3 hunks)
  • app/res/values-hi/strings.xml (3 hunks)
  • app/res/values-lt/strings.xml (2 hunks)
  • app/res/values-no/strings.xml (2 hunks)
  • app/res/values-pt/strings.xml (3 hunks)
  • app/res/values-sw/strings.xml (3 hunks)
  • app/res/values-ti/strings.xml (3 hunks)
  • app/res/values/strings.xml (1 hunks)
  • app/src/org/commcare/connect/network/connectId/PersonalIdApiErrorHandler.java (1 hunks)
  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java (2 hunks)
🧰 Additional context used
🧠 Learnings (12)
📚 Learning: 2025-05-08T11:08:18.530Z
Learnt from: shubham1g5
Repo: dimagi/commcare-android PR: 0
File: :0-0
Timestamp: 2025-05-08T11:08:18.530Z
Learning: PR #3048 "Phase 4 Connect PR" introduces a substantial feature called "Connect" to the CommCare Android app, which includes messaging, job management, delivery tracking, payment processing, authentication flows, and learning modules. It follows a modern architecture using Navigation Components with three navigation graphs, segregated business logic in Manager classes, and proper database persistence.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-07-29T14:11:36.386Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java:0-0
Timestamp: 2025-07-29T14:11:36.386Z
Learning: In ConnectJobsListsFragment.java error handling for JSON parsing, if the JSONObject obj is null when passed to handleCorruptJob(), the team prefers to let the code crash rather than adding defensive null checks. This follows the fail-fast philosophy used throughout the Connect feature to catch programming errors immediately rather than masking them.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-06-06T19:54:26.428Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/fragments/connect/ConnectDownloadingFragment.java:74-78
Timestamp: 2025-06-06T19:54:26.428Z
Learning: In ConnectDownloadingFragment.java and similar Connect-related code, the team prefers to let "should never happen" scenarios like null app records crash rather than add defensive null checks, following a fail-fast philosophy to catch programming errors during development.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-07-29T14:10:58.243Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java:0-0
Timestamp: 2025-07-29T14:10:58.243Z
Learning: In ConnectJobsListsFragment.java, the team intentionally uses different error handling strategies: JSONException should throw RuntimeException to crash the app (fail-fast for data contract violations), while IOException should be logged and allow graceful continuation (for network/stream issues). This follows the established Connect module pattern of treating different exception types differently based on their nature.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-05-09T10:57:41.073Z
Learnt from: Jignesh-dimagi
Repo: dimagi/commcare-android PR: 3093
File: app/res/navigation/nav_graph_connect_messaging.xml:41-45
Timestamp: 2025-05-09T10:57:41.073Z
Learning: In the CommCare Android codebase, the navigation graph for Connect messaging (`nav_graph_connect_messaging.xml`) intentionally uses `channel_id` as the argument name in the connectMessageFragment, despite using `channelId` in other parts of the same navigation graph. This naming difference is by design in the refactored code.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-06-20T15:51:14.157Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/models/connect/ConnectLoginJobListModel.java:79-92
Timestamp: 2025-06-20T15:51:14.157Z
Learning: The ConnectLoginJobListModel class in app/src/org/commcare/models/connect/ConnectLoginJobListModel.java does not need to implement Parcelable interface as it is not passed between Android activities or fragments.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-05-22T14:28:35.959Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3121
File: app/src/org/commcare/activities/CommCareSetupActivity.java:360-364
Timestamp: 2025-05-22T14:28:35.959Z
Learning: In CommCareSetupActivity.java, the call to installFragment.showConnectErrorMessage() after fragment transactions is intentionally unguarded with null checks. This follows the app's design pattern where critical error paths prefer immediate crashes over silent failures, making potential issues immediately visible during development rather than hiding them with defensive programming.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-04-18T20:13:29.655Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3040
File: app/src/org/commcare/android/database/connect/models/ConnectJobDeliveryFlagRecord.java:39-55
Timestamp: 2025-04-18T20:13:29.655Z
Learning: In the CommCare Android Connect feature, the JSON object passed to `ConnectJobDeliveryFlagRecord.fromJson()` method should never be null based on the implementation design.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-06-04T19:17:21.213Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/fragments/connect/ConnectUnlockFragment.java:62-64
Timestamp: 2025-06-04T19:17:21.213Z
Learning: In ConnectUnlockFragment.java, the user prefers to let getArguments() potentially throw NullPointerException rather than adding null checks, as the arguments are required for proper navigation flow and their absence indicates a programming error that should fail fast.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-03-10T08:16:59.436Z
Learnt from: shubham1g5
Repo: dimagi/commcare-android PR: 2949
File: app/src/org/commcare/fragments/connectId/ConnectIDSecondaryPhoneNumber.java:58-59
Timestamp: 2025-03-10T08:16:59.436Z
Learning: All fragments using view binding should implement proper cleanup in onDestroyView() by setting binding to null to prevent memory leaks.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-05-22T14:32:53.133Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3121
File: app/res/values-ti/strings.xml:350-350
Timestamp: 2025-05-22T14:32:53.133Z
Learning: PersonalID and Connect features haven't been translated to Spanish, Lithuanian, or Norwegian yet, so users with those language settings see the English strings by default.

Applied to files:

  • app/res/values-es/strings.xml
📚 Learning: 2025-06-13T15:53:12.951Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/connect/network/PersonalIdApiHandler.java:51-56
Timestamp: 2025-06-13T15:53:12.951Z
Learning: For `PersonalIdApiHandler`, the team’s convention is to propagate `JSONException` as an unchecked `RuntimeException` so the app crashes, signalling a contract/implementation bug rather than attempting a graceful retry.

Applied to files:

  • app/src/org/commcare/connect/network/connectId/PersonalIdApiErrorHandler.java
🔇 Additional comments (11)
app/res/values/strings.xml (1)

701-702: Generic 403 error string looks appropriate

network_forbidden_error is clear, context-agnostic, and reuses existing “contact customer support if the problem persists” phrasing; no issues from a UX or technical standpoint.

app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java (1)

135-137: Navigation call reformatting only

The navigate(…ConnectDownloadingFragment(...)) call and closing brace changes are indentation-only; arguments and control flow are unchanged.

Also applies to: 274-274

app/res/values-no/strings.xml (1)

103-107: Norwegian network error strings align with base resources

New recovery_network_* and network_forbidden_error entries mirror the English keys and have no format specifiers, so there’s no risk of placeholder mismatches.

Also applies to: 135-136

app/res/values-lt/strings.xml (1)

103-107: Lithuanian network error translations look structurally correct

The added recovery_network_* and network_forbidden_error strings match the base keys and avoid format placeholders, so they’re safe from formatting/runtime issues.

Also applies to: 135-136

app/res/values-fr/strings.xml (1)

186-188: French recovery and forbidden network messages are consistent with English

All new recovery_network_* and network_forbidden_error resources correspond 1:1 with the base keys, with no format arguments and idiomatic “réessayer / contacter le service client” phrasing; technically sound.

Also applies to: 521-521, 531-531

app/res/values-ti/strings.xml (1)

174-176: Tigrinya network error strings are structurally safe

recovery_network_* and network_forbidden_error are added with the expected keys and no % placeholders, so they won’t introduce formatting or runtime issues; fallback to English is unnecessary here.

Also applies to: 510-510, 519-519

app/res/values-sw/strings.xml (1)

187-189: Swahili network error localizations match the new error handling contract

The added recovery_network_* and network_forbidden_error strings use the same keys as the base locale, include no format specifiers, and read consistently with the English originals.

Also applies to: 527-527, 536-536

app/src/org/commcare/connect/network/connectId/PersonalIdApiErrorHandler.java (1)

56-58: FORBIDDEN_ERROR now correctly uses a generic 403 message

Switching the FORBIDDEN_ERROR case to R.string.network_forbidden_error removes the PersonalID‑specific copy from generic 403 handling while keeping the error taxonomy intact; matches the new string resources and PR intent.

app/res/values-pt/strings.xml (1)

186-188: Localization additions look good.

All five expected network error message strings are present in Portuguese with appropriate translations. The additions are properly formatted and purely additive, with no modifications to existing keys.

Also applies to: 527-527, 536-536

app/res/values-hi/strings.xml (1)

186-188: Localization additions complete and properly formatted.

All five network error message strings are present in Hindi with consistent XML formatting. The additions align with the Portuguese locale and support the PR's goal to generalize error messaging across all locales without modifying existing keys.

Also applies to: 516-516, 526-526

app/res/values-es/strings.xml (1)

123-125: Localization additions consistent and comprehensive.

All five network error message strings are present in Spanish with correct XML formatting. This completes the localization coverage across the three locales reviewed (Portuguese, Hindi, and Spanish). The additions are purely additive and align the Spanish translations with the other locales, supporting the PR's objective to generalize 403 error handling across all language variants.

Also applies to: 518-518, 528-528


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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java (3)

35-35: Align enum type usage for API error codes

You now import BaseApiHandler and reference BaseApiHandler.PersonalIdOrConnectApiErrorCodes in handleApiErrorCode, while onFailure still uses the bare PersonalIdOrConnectApiErrorCodes type. Please double‑check that:

  • Both refer to the same enum, and
  • You have an explicit import for whichever nested type owns PersonalIdOrConnectApiErrorCodes,

so there’s no ambiguity or accidental duplication. It may be clearer to standardize on a single fully qualified owner + import and use the same simple type name everywhere.


83-88: Centralizing error handling looks good; consider skipping empty messages

Routing onFailure through handleApiErrorCode is a nice cleanup and makes the 403 override straightforward. One small improvement: PersonalIdApiErrorHandler.handle can intentionally return an empty string (e.g., when it has already handled the UX), but this path will still show a blank Toast.

Consider only showing the Toast when there is a non‑empty message, e.g.:

-String errorMessage = handleApiErrorCode(errorCode, t);
-Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_LONG).show();
+String errorMessage = handleApiErrorCode(errorCode, t);
+if (!errorMessage.isEmpty()) {
+    Toast.makeText(requireContext(), errorMessage, Toast.LENGTH_LONG).show();
+}

This keeps behavior cleaner while preserving existing error handling.


102-119: Finalize 403 mapping and reconcile with existing FORBIDDEN_ERROR handling

The new handleApiErrorCode helper cleanly centralizes the “403 for opportunities refresh” behavior, but right now the FORBIDDEN case still returns the generic recovery_network_server_error with a TODO. That doesn’t yet encode the product‑specific copy described in the PR, and it also overrides the existing FORBIDDEN_ERROR message defined in PersonalIdApiErrorHandler.

Before merging, it would be good to:

  • Introduce and wire up the finalized string resource that product wants for this scenario (instead of the generic server‑error string), and
  • Confirm that this divergence from the global FORBIDDEN_ERROR message is intentional for this fragment.

Optionally, while the underlying 403 cause is still being investigated, consider logging t in this branch for easier debugging.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a81e3a5 and 2788def.

📒 Files selected for processing (1)
  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java (3 hunks)
🧰 Additional context used
🧠 Learnings (12)
📓 Common learnings
Learnt from: shubham1g5
Repo: dimagi/commcare-android PR: 0
File: :0-0
Timestamp: 2025-05-08T11:08:18.530Z
Learning: PR #3048 "Phase 4 Connect PR" introduces a substantial feature called "Connect" to the CommCare Android app, which includes messaging, job management, delivery tracking, payment processing, authentication flows, and learning modules. It follows a modern architecture using Navigation Components with three navigation graphs, segregated business logic in Manager classes, and proper database persistence.
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java:0-0
Timestamp: 2025-07-29T14:10:58.243Z
Learning: In ConnectJobsListsFragment.java, the team intentionally uses different error handling strategies: JSONException should throw RuntimeException to crash the app (fail-fast for data contract violations), while IOException should be logged and allow graceful continuation (for network/stream issues). This follows the established Connect module pattern of treating different exception types differently based on their nature.
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java:0-0
Timestamp: 2025-07-29T14:11:36.386Z
Learning: In ConnectJobsListsFragment.java error handling for JSON parsing, if the JSONObject obj is null when passed to handleCorruptJob(), the team prefers to let the code crash rather than adding defensive null checks. This follows the fail-fast philosophy used throughout the Connect feature to catch programming errors immediately rather than masking them.
Learnt from: pm-dimagi
Repo: dimagi/commcare-android PR: 2956
File: app/src/org/commcare/fragments/connectMessaging/ConnectMessageChannelListFragment.java:58-60
Timestamp: 2025-02-19T15:15:01.935Z
Learning: Error handling for message retrieval in ConnectMessageChannelListFragment's retrieveMessages callback is not required as per user preference.
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/fragments/connect/ConnectDeliveryDetailsFragment.java:163-180
Timestamp: 2025-06-06T19:52:53.173Z
Learning: In the CommCare Android Connect feature, database operations like ConnectJobUtils.upsertJob should be allowed to crash rather than being wrapped in try-catch blocks. The team prefers fail-fast behavior for database errors instead of graceful error handling.
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectUnlockFragment.java:0-0
Timestamp: 2025-07-29T14:08:55.466Z
Learning: In ConnectUnlockFragment.java and similar Connect-related code, the team has agreed that JSONExceptions should crash the app by throwing RuntimeException (fail-fast approach for data contract violations), while IOExceptions should be logged and allow processing to continue (graceful handling for network/stream issues). This intentional inconsistency in error handling reflects different treatment for different types of failures.
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3121
File: app/src/org/commcare/activities/CommCareSetupActivity.java:360-364
Timestamp: 2025-05-22T14:28:35.959Z
Learning: In CommCareSetupActivity.java, the call to installFragment.showConnectErrorMessage() after fragment transactions is intentionally unguarded with null checks. This follows the app's design pattern where critical error paths prefer immediate crashes over silent failures, making potential issues immediately visible during development rather than hiding them with defensive programming.
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectUnlockFragment.java:0-0
Timestamp: 2025-07-29T14:10:55.131Z
Learning: In ConnectUnlockFragment.java, opportunityId values are expected to always contain valid integer strings. Integer.parseInt() should be allowed to throw NumberFormatException if invalid data is encountered, following the fail-fast philosophy used throughout the Connect feature for data contract violations.
📚 Learning: 2025-07-29T14:10:58.243Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java:0-0
Timestamp: 2025-07-29T14:10:58.243Z
Learning: In ConnectJobsListsFragment.java, the team intentionally uses different error handling strategies: JSONException should throw RuntimeException to crash the app (fail-fast for data contract violations), while IOException should be logged and allow graceful continuation (for network/stream issues). This follows the established Connect module pattern of treating different exception types differently based on their nature.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-07-29T14:11:36.386Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java:0-0
Timestamp: 2025-07-29T14:11:36.386Z
Learning: In ConnectJobsListsFragment.java error handling for JSON parsing, if the JSONObject obj is null when passed to handleCorruptJob(), the team prefers to let the code crash rather than adding defensive null checks. This follows the fail-fast philosophy used throughout the Connect feature to catch programming errors immediately rather than masking them.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-05-22T14:28:35.959Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3121
File: app/src/org/commcare/activities/CommCareSetupActivity.java:360-364
Timestamp: 2025-05-22T14:28:35.959Z
Learning: In CommCareSetupActivity.java, the call to installFragment.showConnectErrorMessage() after fragment transactions is intentionally unguarded with null checks. This follows the app's design pattern where critical error paths prefer immediate crashes over silent failures, making potential issues immediately visible during development rather than hiding them with defensive programming.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-05-08T11:08:18.530Z
Learnt from: shubham1g5
Repo: dimagi/commcare-android PR: 0
File: :0-0
Timestamp: 2025-05-08T11:08:18.530Z
Learning: PR #3048 "Phase 4 Connect PR" introduces a substantial feature called "Connect" to the CommCare Android app, which includes messaging, job management, delivery tracking, payment processing, authentication flows, and learning modules. It follows a modern architecture using Navigation Components with three navigation graphs, segregated business logic in Manager classes, and proper database persistence.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-07-29T14:10:55.131Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectUnlockFragment.java:0-0
Timestamp: 2025-07-29T14:10:55.131Z
Learning: In ConnectUnlockFragment.java, opportunityId values are expected to always contain valid integer strings. Integer.parseInt() should be allowed to throw NumberFormatException if invalid data is encountered, following the fail-fast philosophy used throughout the Connect feature for data contract violations.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-02-19T15:15:01.935Z
Learnt from: pm-dimagi
Repo: dimagi/commcare-android PR: 2956
File: app/src/org/commcare/fragments/connectMessaging/ConnectMessageChannelListFragment.java:58-60
Timestamp: 2025-02-19T15:15:01.935Z
Learning: Error handling for message retrieval in ConnectMessageChannelListFragment's retrieveMessages callback is not required as per user preference.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-07-29T14:08:55.466Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3248
File: app/src/org/commcare/fragments/connect/ConnectUnlockFragment.java:0-0
Timestamp: 2025-07-29T14:08:55.466Z
Learning: In ConnectUnlockFragment.java and similar Connect-related code, the team has agreed that JSONExceptions should crash the app by throwing RuntimeException (fail-fast approach for data contract violations), while IOExceptions should be logged and allow processing to continue (graceful handling for network/stream issues). This intentional inconsistency in error handling reflects different treatment for different types of failures.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-06-06T19:52:53.173Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/fragments/connect/ConnectDeliveryDetailsFragment.java:163-180
Timestamp: 2025-06-06T19:52:53.173Z
Learning: In the CommCare Android Connect feature, database operations like ConnectJobUtils.upsertJob should be allowed to crash rather than being wrapped in try-catch blocks. The team prefers fail-fast behavior for database errors instead of graceful error handling.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-06-06T19:54:26.428Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/fragments/connect/ConnectDownloadingFragment.java:74-78
Timestamp: 2025-06-06T19:54:26.428Z
Learning: In ConnectDownloadingFragment.java and similar Connect-related code, the team prefers to let "should never happen" scenarios like null app records crash rather than add defensive null checks, following a fail-fast philosophy to catch programming errors during development.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-05-22T14:26:41.341Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3121
File: app/src/org/commcare/fragments/SelectInstallModeFragment.java:201-205
Timestamp: 2025-05-22T14:26:41.341Z
Learning: In SelectInstallModeFragment.java, the showConnectErrorMessage method intentionally omits null checks because it's called at a specific point in the startup flow where UI is guaranteed to be loaded. It's designed to crash if activity or view is null to make potential issues immediately visible rather than hiding them with defensive programming.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
📚 Learning: 2025-06-06T20:15:21.134Z
Learnt from: OrangeAndGreen
Repo: dimagi/commcare-android PR: 3108
File: app/src/org/commcare/fragments/connect/ConnectJobIntroFragment.java:65-71
Timestamp: 2025-06-06T20:15:21.134Z
Learning: In the CommCare Android Connect module, job.getLearnAppInfo() and getLearnModules() should never return null according to the system design. The team prefers to let the code crash if these values are unexpectedly null rather than adding defensive null checks, following a fail-fast philosophy to catch bugs early rather than masking them.

Applied to files:

  • app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java
🧬 Code graph analysis (1)
app/src/org/commcare/fragments/connect/ConnectJobsListsFragment.java (1)
app/src/org/commcare/connect/network/connectId/PersonalIdApiErrorHandler.java (1)
  • PersonalIdApiErrorHandler (26-72)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Lint Code Base

Copy link
Contributor

@shubham1g5 shubham1g5 left a comment

Choose a reason for hiding this comment

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

Think the problem we want to solve here is the default error handling in here. Given this method is used to determine all errors it should adopt more generalised messaging and any classes that want more specific error messaging should instead overide this error handling in their onFailure implementations.

Here I think the right approach is -

  1. Change FORBIDDEN_ERROR message to say something generalised - Access denied by server, Please contact customer support if the problem persists

  2. Use the current error message Unfortunately, this device did not pass the security checks required to sign up for PersonalID. Please try again on a different device. only in onFailure implementation for Personal ID Phone page (first page in sign up process) as that's the only place we are doing security checks.

@conroy-ricketts
Copy link
Contributor Author

@shubham1g5

Change FORBIDDEN_ERROR message to say something generalised - Access denied by server, Please contact customer support if the problem persists

What are your thoughts on the contentions Kim raised in Slack? I don't want to completely dismiss input from someone with Product UX experience:

Especially because we don’t know the root cause, it’d make sense to put something like “Something went wrong, please try XYZ again”, but... any error message for this ending with “please try XYZ again” might be misleading if that’s not actually going to fix the issue... and an error message just saying “Something went wrong” or a similar wording, would honestly just be irritating
... in this particular case, I’m really hesitant to have a generic error message and follow it up with “please try again on a different device”, you know? Asking someone to try again is relatively low effort, asking someone to get a new device and try the same thing again is very high effort so I’d want to give them a reason they need to switch devices
... while the current message is misleading in the reasoning, it’s not necessarily misleading in that they need to use a different device
... unless we’re talking about a really really long timeline (like months), I’m hesitant to change that error message unless we have something better (like the actual reason why we’re throwing it and why they need to switch to a different device)

I see there's been more chatter in the ticket comments about new findings by Charl. Are we closer to pinpointing the exact root cause of the issue? Is it actually just an expired token that caused it? It seems like the error code may have been totally wrong from server

@shubham1g5
Copy link
Contributor

shubham1g5 commented Dec 3, 2025

@conroy-ricketts The errror message to say Unfortunately, this device did not pass the security checks required to sign up for PersonalID. doesn't make sense at all when user is not trying to sign up at all on a screen, this error message was only meant to be used during Personal ID signup on the phone screen as that's where we check the user eligibility for sign up on server.

That is I am not seeing this error change as enehcing messaging but more like fixing a bug that was un-intentionally introduced in code base. To resolve this, we need to find a generalised default error message for 403 and that is where Kim's suggestions seems valid to me. We do know what a 403 means in general on server and we should use that to deduce a generalised message here.I agree on not using terminology like "Try Again" though.

It seems like the error code may have been totally wrong from server

Even if the error code is incorrect from server, we still need to correct default 403 error messaging on the app as there can be valid scenarious in which server might reply with a 403 in future and showing the current error message would be wrong in that case.

@conroy-ricketts
Copy link
Contributor Author

@shubham1g5 Agreed, that makes sense to me! I'll update this and re-request your review when I pull this PR out of draft

Reverted changes made to the ConnectJobsListsFragment.
Added new string resource for general 403 forbidden error message.
Added missing translations for recovery_network_token_unavailable.
Added missing translations for recovery_network_unauthorized.
Added missing translations for recovery_network_token_unavailable that I missed in an earlier commit.
Added missing translations for recovery_network_server_error.
Added missing translations for recovery_network_unknown.
Added strings including non-English translations for network_forbidden_error.
Escaped a character in the French translation for recovery_network_server_error.
@conroy-ricketts
Copy link
Contributor Author

@coderabbitai help

@coderabbitai
Copy link

coderabbitai bot commented Dec 3, 2025

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

CodeRabbit commands

These commands are invoked using PR/Issue comments.

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai evaluate custom pre-merge check --instructions <custom-checks-instructions> --name <custom-checks-title> [--mode <error|warning>] to validate the custom pre-merge checks instructions. Defaults to error when --mode is omitted.
    • @coderabbitai ignore pre-merge checks to override pre-merge checks and get an approval on PR.
    • @coderabbitai run pre-merge checks to run pre-merge checks on the pull request.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit configuration file (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, support, documentation and community

  • Visit our status page to check the current availability of CodeRabbit.
  • Create a ticket on our support page for assistance with any issues or questions.
  • Visit our documentation site for detailed information on how to use CodeRabbit.
  • Join our Discord community to connect with other users and get help from the community.
  • Follow us on X/Twitter for updates and announcements.

@conroy-ricketts
Copy link
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link

coderabbitai bot commented Dec 3, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@OrangeAndGreen OrangeAndGreen left a comment

Choose a reason for hiding this comment

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

Thanks for filling in the missing string translations!

return context.getString(R.string.personalid_configuration_locked_account);
case FORBIDDEN_ERROR:
return context.getString(R.string.personalid_configuration_process_failed_subtitle);
return context.getString(R.string.network_forbidden_error);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not related to this PR but I think we should name this class PersonalIdOrConnectApiErrorHandler from PersonalIdApiErrorHandler

Copy link
Contributor

Choose a reason for hiding this comment

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

@also, do we know when network_forbidden_error is thrown to user?

Copy link
Contributor

Choose a reason for hiding this comment

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

for a 403 response code

Copy link
Contributor

Choose a reason for hiding this comment

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

for a 403 response code

Yeah so 403 is when token is invalid or expired or it can happen in other cases too?

Copy link
Contributor

Choose a reason for hiding this comment

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

401 is what should happen for the case you described, 403 is more like you are banned by server even after having a successful auth (like failing integrity check for example or if server notices anything suspicious about request) . Another example can be user trying to request data that user doesn't have permission to , for exmaple requesting an opportunity data which belongs to a different org than what user belongs to. These are just hypothetical examples though and may or may not be applicable for different endpoints we have.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not related to this PR but I think we should name this class PersonalIdOrConnectApiErrorHandler from PersonalIdApiErrorHandler

I actually think this is a good idea! I'm going to push a quick commit for this @Jignesh-dimagi

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oooh nevermind, the changelist is pretty big. I'll do this in a new PR

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@conroy-ricketts conroy-ricketts merged commit daadcb7 into master Dec 4, 2025
8 checks passed
@conroy-ricketts conroy-ricketts deleted the task/CI-418-opportunities-not-refreshing branch December 4, 2025 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants