Skip to content

Conversation

@jaypanchal-13
Copy link
Contributor

@jaypanchal-13 jaypanchal-13 commented Jul 2, 2025

Product Description

Ticket-> https://dimagi.atlassian.net/browse/CCCT-1396

  • Handle specific locked account error when api respond error
  • As of now integrity api is failing so not able to test and verify it

Technical Summary

Feature Flag

Safety Assurance

Safety story

Automated test coverage

QA Plan

Labels and Review

  • Do we need to enhance the manual QA test coverage ? If yes, the "QA Note" label is set correctly
  • Does the PR introduce any major changes worth communicating ? If yes, the "Release Note" label is set and a "Release Note" is specified in PR description.
  • Risk label is set correctly
  • The set of people pinged as reviewers is appropriate for the level of risk of the change

@coderabbitai
Copy link

coderabbitai bot commented Jul 2, 2025

📝 Walkthrough

Walkthrough

This change introduces enhanced handling for locked account scenarios in the PersonalID feature. A new string resource, personalid_configuration_locked_account, is added to English, French, Portuguese, Swahili, and Tigrinya localization files, providing a user-facing message for locked accounts. The backend error handling is updated: when a 403 Forbidden HTTP response is received, the code now checks for a specific "LOCKED_ACCOUNT" error code in the response body and triggers a dedicated callback if found. An ACCOUNT_LOCKED_ERROR value is added to the relevant error code enum, and the PersonalIdPhoneFragment now explicitly handles this case. Additionally, a new analytics parameter constant is introduced for tracking locked account failures.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant Server

    User->>App: Initiate PersonalID configuration
    App->>Server: Send configuration request
    Server-->>App: Responds with HTTP 403 + error_code ("LOCKED_ACCOUNT")
    App->>App: Parse error_code from response
    alt error_code == "LOCKED_ACCOUNT"
        App->>App: Trigger ACCOUNT_LOCKED_ERROR handling
        App->>User: Display "account locked" message (localized)
        App->>Analytics: Log START_CONFIGURATION_LOCKED_ACCOUNT_FAILURE
    else error_code != "LOCKED_ACCOUNT"
        App->>App: Handle as generic FORBIDDEN_ERROR
        App->>User: Display generic forbidden message
    end
Loading

Suggested reviewers

  • pm-dimagi
  • shubham1g5
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in a Comment
  • Commit Unit Tests in branch CCCT-1396-locked-account-error-handle

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
🪧 Tips

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.
    • Explain this complex logic.
    • 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. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR 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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve 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 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.
  • 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

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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/res/values/strings.xml (1)

601-601: String key added correctly; punctuation style minor

Key/value pair looks fine and matches naming convention used for other PersonalID errors.
Optional: many user-facing sentences in this file end with a period. Consider appending “.” to keep punctuation consistent, but not blocking.

app/src/org/commcare/google/services/analytics/AnalyticsParamValue.java (1)

178-182: Constant follows existing pattern – keep section sorted

Constant name and value are consistent with neighbouring keys.
If you ever rely on alphabetical scans/merge conflict reduction, consider keeping this small block sorted (INTEGRITY_CHECK, INTEGRITY_DEVICE, LOCKED_ACCOUNT) – not required for correctness.

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

449-449: Translation added; minor localisation nit

Translation reads well. Two tiny points you may want to double-check:

  1. Terminology: most of the file uses Brazilian Portuguese (“contato”) rather than European (“contacto”); keep consistency if that’s intentional.
  2. Add a final period to match nearby sentences.

Not blocking.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fc49add and ea079c4.

📒 Files selected for processing (9)
  • app/res/values-fr/strings.xml (1 hunks)
  • app/res/values-pt/strings.xml (1 hunks)
  • app/res/values-sw/strings.xml (1 hunks)
  • app/res/values-ti/strings.xml (1 hunks)
  • app/res/values/strings.xml (1 hunks)
  • app/src/org/commcare/connect/network/base/BaseApiCallback.kt (1 hunks)
  • app/src/org/commcare/connect/network/base/BaseApiHandler.kt (1 hunks)
  • app/src/org/commcare/fragments/personalId/PersonalIdPhoneFragment.java (1 hunks)
  • app/src/org/commcare/google/services/analytics/AnalyticsParamValue.java (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: pm-dimagi
PR: dimagi/commcare-android#2949
File: app/src/org/commcare/fragments/connectId/ConnectIdBiometricConfigFragment.java:95-131
Timestamp: 2025-02-04T21:38:11.970Z
Learning: Biometric authentication security improvements were considered but skipped in PR #2949 as per user's request. The implementation remained with basic biometric authentication without additional security layers.
Learnt from: shubham1g5
PR: dimagi/commcare-android#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
PR: dimagi/commcare-android#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.
app/res/values/strings.xml (2)
Learnt from: Jignesh-dimagi
PR: dimagi/commcare-android#3070
File: app/res/values/strings.xml:73-73
Timestamp: 2025-05-07T06:50:52.518Z
Learning: The empty `remote_form_payload_url` string resource in strings.xml is intentional legacy code and should be preserved as-is.
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
app/src/org/commcare/connect/network/base/BaseApiHandler.kt (1)
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
app/res/values-pt/strings.xml (1)
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
app/res/values-ti/strings.xml (2)
Learnt from: Jignesh-dimagi
PR: dimagi/commcare-android#3070
File: app/res/values/strings.xml:73-73
Timestamp: 2025-05-07T06:50:52.518Z
Learning: The empty `remote_form_payload_url` string resource in strings.xml is intentional legacy code and should be preserved as-is.
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
app/res/values-fr/strings.xml (1)
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
app/src/org/commcare/connect/network/base/BaseApiCallback.kt (3)
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#2912
File: app/src/org/commcare/fragments/connectId/ConnectIdPasswordVerificationFragment.java:206-213
Timestamp: 2025-01-21T18:20:43.883Z
Learning: In the Connect ID feature, server responses containing user data should be parsed using ConnectUserResponseParser to ensure consistent handling of payment information (owner_name and phone_number) and secondary phone verification across all authentication flows.
Learnt from: pm-dimagi
PR: dimagi/commcare-android#2949
File: app/src/org/commcare/fragments/connectId/ConnectIdPinFragment.java:244-275
Timestamp: 2025-02-04T21:22:56.537Z
Learning: Direct JSONObject parsing is acceptable for handling user data responses in ConnectIdPinFragment, as decided by the team. No need to enforce ConnectUserResponseParser usage in this context.
app/res/values-sw/strings.xml (1)
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
app/src/org/commcare/fragments/personalId/PersonalIdPhoneFragment.java (10)
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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
PR: dimagi/commcare-android#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.
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#2912
File: app/src/org/commcare/fragments/connect/ConnectPaymentSetupFragment.java:61-66
Timestamp: 2025-01-21T17:29:58.014Z
Learning: In the CommCare Android app, for non-critical convenience features like phone number auto-population, exceptions should be logged but fail silently when there's a manual fallback available. This approach prevents app crashes while maintaining the ability to debug issues through logs.
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
Learnt from: shubham1g5
PR: dimagi/commcare-android#2949
File: app/src/org/commcare/fragments/connectId/ConnectIdPasswordVerificationFragment.java:173-247
Timestamp: 2025-03-10T08:16:29.416Z
Learning: In the ConnectIdPasswordVerificationFragment, password comparisons should use MessageDigest.isEqual() rather than equals() to prevent timing attacks, and empty password validation should be implemented before verification attempts.
Learnt from: pm-dimagi
PR: dimagi/commcare-android#2949
File: app/src/org/commcare/fragments/connectId/ConnectIdBiometricConfigFragment.java:235-236
Timestamp: 2025-02-04T21:29:29.594Z
Learning: The empty performPasswordUnlock method in ConnectIdBiometricConfigFragment is intentionally left empty and should not be flagged in reviews.
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#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.
Learnt from: shubham1g5
PR: dimagi/commcare-android#3116
File: app/src/org/commcare/fragments/connectId/PersonalIdPhotoCaptureFragment.java:0-0
Timestamp: 2025-05-19T15:36:34.511Z
Learning: In the CommCare Android codebase, a "fail fast" approach is preferred for internal encoding/decoding operations where both sides are controlled by the application. This helps surface bugs immediately rather than masking them with graceful error handling.
Learnt from: Jignesh-dimagi
PR: dimagi/commcare-android#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.
Learnt from: OrangeAndGreen
PR: dimagi/commcare-android#2927
File: app/src/org/commcare/activities/connect/HQUserInviteActivity.java:0-0
Timestamp: 2025-02-04T15:29:12.993Z
Learning: In HQUserInviteActivity, parameters from Intent data (domain, inviteCode, username, etc.) are required and the code is designed to fail immediately if they're missing, rather than adding null checks. This helps catch integration issues early.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Lint Code Base
🔇 Additional comments (6)
app/src/org/commcare/connect/network/base/BaseApiHandler.kt (1)

30-31: LGTM! Enum addition is correctly implemented.

The new ACCOUNT_LOCKED_ERROR enum value is properly positioned and follows the existing naming convention. The shouldAllowRetry() method correctly excludes this error code, which is appropriate since locked accounts should not automatically retry.

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

449-449: LGTM! Localized string resource correctly added.

The new personalid_configuration_locked_account string resource provides an appropriate Swahili message for locked account scenarios, guiding users to contact support. The addition is consistent with the broader localization strategy for the PersonalID feature.

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

435-435: LGTM! Tigrinya localization correctly implemented.

The new personalid_configuration_locked_account string resource provides a clear Tigrinya message for locked account scenarios, directing users to contact support. This addition maintains consistency with the localization strategy across language files for the PersonalID feature.

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

443-443: LGTM: French localization added correctly.

The French translation for the locked account message is grammatically correct and appropriately conveys the error state to users.

app/src/org/commcare/connect/network/base/BaseApiCallback.kt (1)

32-50: LGTM: Robust error handling implementation.

The enhanced 403 error handling properly:

  • Parses JSON response body to detect specific "LOCKED_ACCOUNT" error codes
  • Uses proper resource management with the use block
  • Handles parsing failures gracefully with exception logging
  • Falls back to existing behavior when error code doesn't match
  • Uses case-insensitive comparison to handle server response variations
app/src/org/commcare/fragments/personalId/PersonalIdPhoneFragment.java (1)

361-385: LGTM: Improved error handling with specific locked account case.

The enhanced error handling properly:

  • Adds null check to prevent potential NPE
  • Uses switch statement for better maintainability
  • Provides specific handling for ACCOUNT_LOCKED_ERROR with appropriate analytics and user messaging
  • Preserves existing FORBIDDEN_ERROR behavior
  • Ensures all other errors are handled by the default case

Comment on lines 32 to 46
if (errorResponse != null){
try {
errorResponse.use {
val json = JSONObject(String(StreamsUtil.inputStreamToByteArray(it), Charsets.UTF_8))
if (json.has("error_code")){
val errorCode = json.optString("error_code")
if (errorCode.equals("LOCKED_ACCOUNT", ignoreCase = true)) {
baseApiHandler.onFailure(
PersonalIdOrConnectApiErrorCodes.ACCOUNT_LOCKED_ERROR,
null
)
return
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

@jaypanchal-13 we want to do this for all response codes and not just 403.

Copy link
Contributor Author

@jaypanchal-13 jaypanchal-13 Jul 2, 2025

Choose a reason for hiding this comment

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

@shubham1g5 checked with charl on this. He informed this locked account will only come with 403 error code and not with any other

Copy link
Contributor

Choose a reason for hiding this comment

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

that's true but we want to have support for error_code for all response codes on mobile.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jaypanchal-13 jaypanchal-13 requested a review from shubham1g5 July 3, 2025 05:23
@Jignesh-dimagi
Copy link
Contributor

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@jaypanchal-13
Copy link
Contributor Author

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@Jignesh-dimagi for backup code @OrangeAndGreen has already completed that

@Jignesh-dimagi
Copy link
Contributor

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@Jignesh-dimagi for backup code @OrangeAndGreen has already completed that

Yes correct when response is 200 but not for failure

@jaypanchal-13
Copy link
Contributor Author

jaypanchal-13 commented Jul 3, 2025

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@Jignesh-dimagi for backup code @OrangeAndGreen has already completed that

Yes correct when response is 200 but not for failure

@Jignesh-dimagi Please check my last commit in this PR, have added gerneralized handling for error_code in BaseApiCallback and as we are getting error_code on success(Handled by Dave)for this backup code api. I don't think to need it in failure part in specific fragment

@Jignesh-dimagi
Copy link
Contributor

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@Jignesh-dimagi for backup code @OrangeAndGreen has already completed that

Yes correct when response is 200 but not for failure

@Jignesh-dimagi Please check my last commit in this PR, have added gerneralized handling for error_code in BaseApiCallback

But you have not handled that failure code in PersonalIdBackupCodeFragment. and showing account lock on PersonalIdMessageFragment which will force user to exit the registration flow.

@jaypanchal-13
Copy link
Contributor Author

jaypanchal-13 commented Jul 3, 2025

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@Jignesh-dimagi for backup code @OrangeAndGreen has already completed that

Yes correct when response is 200 but not for failure

@Jignesh-dimagi Please check my last commit in this PR, have added gerneralized handling for error_code in BaseApiCallback

But you have not handled that failure code in PersonalIdBackupCodeFragment. and showing account lock on PersonalIdMessageFragment which will force user to exit the registration flow.

For confirm_backup_code api application will get error_code in success not in failure. And handling it in success part is done by Dave. I think there is no need to handle error_code for failure for this confirm_backup_code api as we will never get error_code in failure state @shubham1g5 what do you suggest?

@Jignesh-dimagi
Copy link
Contributor

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@Jignesh-dimagi for backup code @OrangeAndGreen has already completed that

Yes correct when response is 200 but not for failure

@Jignesh-dimagi Please check my last commit in this PR, have added gerneralized handling for error_code in BaseApiCallback

But you have not handled that failure code in PersonalIdBackupCodeFragment. and showing account lock on PersonalIdMessageFragment which will force user to exit the registration flow.

For confirm_backup_code api application will get error_code in success not in failure. And handling it in success part is done by Dave. I think there is no need to handle error_code for failure for this confirm_backup_code api as we will never get error_code in failure state @shubham1g5 what do you suggest?

That is strange!, One API is sending error_code in 200 and another api in 403. We should confirm with backend team for the same.

@jaypanchal-13
Copy link
Contributor Author

@jaypanchal-13 When user tries for 3 failed attempt for back up code, we need to lock it there also so need implementation at PersonalIdBackupCodeFragment also.

@Jignesh-dimagi for backup code @OrangeAndGreen has already completed that

Yes correct when response is 200 but not for failure

@Jignesh-dimagi Please check my last commit in this PR, have added gerneralized handling for error_code in BaseApiCallback

But you have not handled that failure code in PersonalIdBackupCodeFragment. and showing account lock on PersonalIdMessageFragment which will force user to exit the registration flow.

For confirm_backup_code api application will get error_code in success not in failure. And handling it in success part is done by Dave. I think there is no need to handle error_code for failure for this confirm_backup_code api as we will never get error_code in failure state @shubham1g5 what do you suggest?

That is strange!, One API is sending error_code in 200 and another api in 403. We should confirm with backend team for the same.

@Jignesh-dimagi Confirmed with charl on this

@jaypanchal-13 jaypanchal-13 changed the title Handled locked account error on api failure(403) Handled locked account error on api failure Jul 3, 2025
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.

can we also add the new string for hindi and spanish.

Comment on lines 58 to 59
Logger.exception("Unhandled API error code: " + errorCode, t);
return activity.getString(R.string.recovery_network_unknown);
Copy link
Contributor

Choose a reason for hiding this comment

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

think what we want to do here is this -

if (t is not null) -> throw new RuntimeException(t);
else -> 
Logger.exception("Unhandled API error code", new RuntimeException("Unhandled API error code: " + errorCode));
return activity.getString(R.string.recovery_network_unknown);

as we should still throw any unhandled exceptions from here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@shubham1g5 We will any way get exception in log why to crash app for it and give poor experience to user? Do you want to change it?

Copy link
Contributor

Choose a reason for hiding this comment

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

The philosophy here is user is much more likely to report a crash to us rather than a silent failure. We prefer to crash hard for any unknown exceptions we didn't anticipate to happen in the code due to external factors. Here is a doc on this approach that gives more details on what we want to catch and what not.


if (responseCode == 429 || responseCode == 503) {
baseApiHandler.onFailure(
429, 503 -> baseApiHandler.onFailure(
Copy link
Contributor

Choose a reason for hiding this comment

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

unrelated to this PR, but think we want to treat all 50x as server errors instead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@shubham1g5 Yes correct but I think before managing all 50X for server errors, backend sholud make sure that in this case 503 is rate limit exceed. Should be modified from backend to avoid any crash regarding this in future. Should I go ahead and manage it from our side?

Copy link
Contributor

Choose a reason for hiding this comment

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

I can confirm that backend sends 429 for rate limiting only and not 503 . This was more of an error on mobile implementation earlier to treat 503 as rate limiting


else -> baseApiHandler.onFailure(
PersonalIdOrConnectApiErrorCodes.UNKNOWN_ERROR,
Exception("Response $responseCode")
Copy link
Contributor

Choose a reason for hiding this comment

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

  • We should ensure that we are handling all possible http response codes in this method above if we are going to throw anything else as unknown error with an exception
  • UNKNOWN_ERROR doesn't log the associated exception in PersonalIdApiErrorHandler.handle , so there is no real value in adding Exception("Response $responseCode") here but we can just log the unknown response code here directly as Logger.exception("Unknown http response code ", new Exception("Encountered response code " + responseCode + " for url " url))

For unknow error thrown exception with url
Added common server error for 50X error codes
@jaypanchal-13 jaypanchal-13 requested a review from shubham1g5 July 4, 2025 11:18
…count-error-handle

# Conflicts:
#	app/res/values-es/strings.xml
@jaypanchal-13 jaypanchal-13 merged commit 806de46 into master Jul 7, 2025
5 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-integration-tests Skip android tests.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants