Skip to content

fix: WEB-862 Localise the error as per the selected language#3407

Open
saksham869 wants to merge 1 commit intoopenMF:devfrom
saksham869:fix/WEB-862-final
Open

fix: WEB-862 Localise the error as per the selected language#3407
saksham869 wants to merge 1 commit intoopenMF:devfrom
saksham869:fix/WEB-862-final

Conversation

@saksham869
Copy link
Copy Markdown
Contributor

@saksham869 saksham869 commented Mar 19, 2026

Description
Error messages in the Mifos web app were always displayed in English regardless of the language selected by the user. Apache Fineract sends two localisation codes in error responses — userMessageGlobalisationCode and errors.userMessageGlobalisationCode — but the error handler interceptor was completely ignoring these and always falling back to defaultUserMessage which is in English.
This PR updates the ErrorHandlerInterceptor to:

Extract userMessageGlobalisationCode from Fineract error responses — checking nested errors first (more specific), then top-level
Pass interpolation args to translate.instant() for parameterized error messages
Use errorMessage || this.translate.instant(...) pattern so server-localized messages are never discarded
Compare invalid token check against stable raw server message instead of localized text
Fix 404 client image handling — invert condition so error flows through to service handler
Use consistent .type and .message key naming throughout

Translation keys added for all HTTP error types (401, 400, 403, 404, 500, 501) across all 14 supported language files including cs-CS, de-DE, en-US, es-CL, es-MX, fr-FR, it-IT, ko-KO, lt-LT, lv-LV, ne-NE, pt-PT, sw-SW.
Related issues and discussion
WEB-862: https://mifosforge.jira.com/browse/WEB-862

Summary by CodeRabbit

  • New Features

    • Added localized error messages for auth, token, bad request, unauthorized, not found, server error, not implemented, and unknown error cases.
  • Bug Fixes

    • Improved error message selection and translation precedence, safer parameter handling, narrowed OAuth-related 400 alerts to token/auth endpoints, and more reliable detection of invalid one-time tokens.
  • Chores

    • Removed an auto-generated runtime environment export that exposed build/runtime metadata.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 19, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'pre_merge_checks'
⚙️ Configuration instructions
  • 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

Walkthrough

Derives HTTP error messages from nested response.error.errors[0] (falling back to top-level fields), prefers nested userMessageGlobalisationCode for translations, tightens OAuth 400 handling to token/auth endpoints, changes 403 OTP invalid detection to use globalisation code, adds new en-US error keys, and deletes src/environments/.env.ts.

Changes

Cohort / File(s) Summary
Error handler
src/app/core/http/error-handler.interceptor.ts
Reworked error-message selection to prefer response.error.errors[0] (using defaultUserMessage/developerMessage fallbacks), consolidated userMessageGlobalisationCode lookup to prefer nested key, apply translations via TranslateService.instant(...) when available, simplified parameterName extraction, limited OAuth-related 400 handling to requests with /oauth/token or /authentication, and updated 403 OTP-invalid detection to check the globalisation code.
Translations
src/assets/translations/en-US.json
Added multiple top-level error translation keys (error.auth.*, error.token.invalid.*, error.bad.request.*, error.unauthorized.*, error.resource.not.found.*, error.server.internal.*, error.resource.notImplemented.*, error.unknown.*) and adjusted comma placement in a validation message.
Env removal
src/environments/.env.ts
Deleted the auto-generated environment module that exported mifos_x (version/hash) and allow_switching_backend_instance configuration.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Client as Client (UI)
participant HTTP as HttpClient
participant Interceptor as ErrorHandlerInterceptor
participant Translate as TranslateService
participant Alert as AlertService

Client->>HTTP: send request
HTTP-->>Client: error response
HTTP->>Interceptor: intercept(error)
Interceptor->>Interceptor: pick message from response.error.errors[0] or fallbacks
Interceptor->>Translate: instant(userMessageGlobalisationCode)
Translate-->>Interceptor: translatedText or key
Interceptor->>Alert: show(type, message)
Alert-->>Client: display alert

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • alberto-art3ch
  • IOhacker
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective: localizing error messages based on the selected language by extracting and using Fineract-provided localization codes in the ErrorHandlerInterceptor.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Copy Markdown
Contributor

@IOhacker IOhacker left a comment

Choose a reason for hiding this comment

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

@saksham869 please review that only one commit is expected and make sure that the title is following the syntax required

@saksham869 saksham869 changed the title Fix/web 862 final fix: WEB-862 Localise the error as per the selected language Mar 19, 2026
@saksham869 saksham869 force-pushed the fix/WEB-862-final branch 3 times, most recently from 2c1f4a9 to 196f3e0 Compare March 19, 2026 19:27
Copy link
Copy Markdown

@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: 4

🧹 Nitpick comments (1)
src/assets/translations/pt-PT.json (1)

11-24: Consider normalizing the 501 key naming style for consistency.

New keys use dotted segments (e.g., error.resource.not.found.*), while the nearby 501 key uses error.resource.notImplemented.*. Keeping both styles aligned reduces future lookup mismatches.

♻️ Optional consistency patch
+    "error.resource.not.implemented.type": "Erro não implementado",
+    "error.resource.not.implemented.message": "Funcionalidade não implementada!",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/assets/translations/pt-PT.json` around lines 11 - 24, The 501-related
keys use a different naming style (e.g.,
error.resource.notImplemented.type/message) which conflicts with the
dotted-segment convention used elsewhere (e.g.,
error.resource.not.found.type/message); rename the 501 keys to follow the dotted
convention (for example error.resource.not.implemented.type and
error.resource.not.implemented.message) and update any lookup sites that
reference the old keys to use the new keys to avoid runtime lookup mismatches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/core/http/error-handler.interceptor.ts`:
- Around line 50-64: The interceptor currently lets
response.error.userMessageGlobalisationCode overwrite a more-specific nested
code and may have initialized errorMessage from developerMessage before checking
nested errors; update the logic in error-handler.interceptor.ts so that you
first prefer and assign nested values
(response.error.errors[0].userMessageGlobalisationCode and
.defaultUserMessage/.developerMessage) to globalisationCode and errorMessage,
and only set globalisationCode from response.error.userMessageGlobalisationCode
if globalisationCode is still null/undefined; ensure errorMessage is not
overwritten by a top-level developerMessage once a nested defaultUserMessage was
chosen.
- Around line 133-136: The catch-all else branch currently discards any resolved
backend message and always uses the generic unknown message; update the else
branch in the error-handling flow (the code that calls alertService.alert and
translate.instant) to prefer the resolved backend message (e.g. the
previously-derived defaultUserMessage or the translated
userMessageGlobalisationCode) when present, and only fall back to
translate.instant('error.unknown.message') if no backend message exists; ensure
you use the same translation helper (translate.instant) for the globalization
code path and pass that resolved string into alertService.alert's message field.
- Around line 109-114: The current branch where isClientImage404 returns a
successful Observable with null swallows the original 404; instead rethrow the
original error so downstream image service can handle it. Replace the return new
Observable(...) in the isClientImage404 branch with a rethrow using
throwError(() => err) (or throwError(() => originalError)) so the interceptor
emits the error rather than a null value; keep the isClientImage404 condition
and use the same err reference available in the interceptor's catch block.
- Around line 67-72: In src/app/core/http/error-handler.interceptor.ts the
hardcoded translation keys (e.g., 'error.auth.type', 'error.token.invalid.*',
'error.bad.request.*', etc.) lack the required "errors." prefix and therefore
fail to resolve; update all those hardcoded keys to include the "errors." prefix
(for example 'error.auth.type' -> 'errors.error.auth.type') and mirror the
existing pattern used around globalisationCode: use translate.instant(...) then
verify the returned value !== key before assigning to errorMessage (referencing
globalisationCode, translate.instant and errorMessage in the interceptor) so
only valid translations replace the fallback.

---

Nitpick comments:
In `@src/assets/translations/pt-PT.json`:
- Around line 11-24: The 501-related keys use a different naming style (e.g.,
error.resource.notImplemented.type/message) which conflicts with the
dotted-segment convention used elsewhere (e.g.,
error.resource.not.found.type/message); rename the 501 keys to follow the dotted
convention (for example error.resource.not.implemented.type and
error.resource.not.implemented.message) and update any lookup sites that
reference the old keys to use the new keys to avoid runtime lookup mismatches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b5d483fe-52d3-4aaa-8f28-18ad8552bde4

📥 Commits

Reviewing files that changed from the base of the PR and between 5e7705b and 1d90eb5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json and included by **/*
📒 Files selected for processing (15)
  • src/app/core/http/error-handler.interceptor.ts
  • src/assets/translations/cs-CS.json
  • src/assets/translations/de-DE.json
  • src/assets/translations/en-US.json
  • src/assets/translations/es-CL.json
  • src/assets/translations/es-MX.json
  • src/assets/translations/fr-FR.json
  • src/assets/translations/it-IT.json
  • src/assets/translations/ko-KO.json
  • src/assets/translations/lt-LT.json
  • src/assets/translations/lv-LV.json
  • src/assets/translations/ne-NE.json
  • src/assets/translations/pt-PT.json
  • src/assets/translations/sw-SW.json
  • src/environments/.env.ts

@saksham869
Copy link
Copy Markdown
Contributor Author

Hi @IOhacker
Thank you for the review. I have addressed both requested changes:

  1. Squashed to a single commit
  2. Updated PR title to follow the required syntax: fix: WEB-862 Localise the error as per the selected language

All CI checks are now passing. Please re-review..
Thank you!

Copy link
Copy Markdown

@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.

♻️ Duplicate comments (4)
src/app/core/http/error-handler.interceptor.ts (4)

109-114: ⚠️ Potential issue | 🟠 Major

Re-throw the client-image 404 instead of converting it to null.

This branch turns the 404 into a successful emission, so downstream handlers never see an error. If the image service is supposed to decide how to handle a missing photo, it needs the original HttpErrorResponse.

In Angular HttpInterceptor with RxJS catchError, does returning an Observable that emits `null` swallow the original `HttpErrorResponse`, and should `throwError(() => error)` be used instead to keep downstream error handlers working?
🔧 Suggested fix
-import { Observable } from 'rxjs';
+import { Observable, throwError } from 'rxjs';
@@
-        return new Observable((observer) => {
-          observer.next(null);
-          observer.complete();
-        });
+        return throwError(() => response);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 109 - 114, The
branch that handles isClientImage404 should re-throw the original
HttpErrorResponse instead of returning an Observable that emits null; update the
logic in the error handling path (in the interceptor method where
isClientImage404 is checked) to return throwError(() => error) (or rethrow the
error via throw) so downstream subscribers and the imaging service receive the
original HttpErrorResponse rather than a successful null emission.

50-64: ⚠️ Potential issue | 🟠 Major

Keep the first nested Fineract error as the winner.

Line 63 still overwrites the errors[0] code selected on Lines 55-57. When Fineract sends both shapes, that replaces the more specific nested message with a generic top-level one and breaks the intended nested-first fallback.

🔧 Suggested fix
-    let errorMessage = response.error?.developerMessage || response.message;
+    let errorMessage = response.error?.defaultUserMessage || response.error?.developerMessage || response.message;
     let globalisationCode: string | null = null;
@@
-    if (response.error?.userMessageGlobalisationCode) {
+    if (!globalisationCode && response.error?.userMessageGlobalisationCode) {
       globalisationCode = response.error.userMessageGlobalisationCode;
+      errorMessage = response.error?.defaultUserMessage || errorMessage;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 50 - 64, The
current logic sets globalisationCode from
response.error.userMessageGlobalisationCode even after selecting the nested
winner from response.error.errors[0], which overwrites the more specific nested
code; update the conditional that checks
response.error?.userMessageGlobalisationCode so it only assigns to
globalisationCode (and does not change errorMessage) if globalisationCode is
still null/undefined after inspecting response.error.errors[0] — reference the
variables response, globalisationCode, errorMessage and the nested
response.error.errors[0] when making this change.

133-137: ⚠️ Potential issue | 🟠 Major

Don't discard the resolved backend message in the catch-all branch.

Statuses like 409, 422, or 503 can already populate errorMessage above, but Line 136 always replaces it with the generic unknown text. That undoes the localization work for every non-enumerated status.

🔧 Suggested fix
     } else {
       this.alertService.alert({
-        type: this.translate.instant('error.unknown.type'),
-        message: this.translate.instant('error.unknown.message')
+        type: this.translate.instant('errors.error.unknown.type'),
+        message: errorMessage || this.translate.instant('errors.error.unknown.message')
       });
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 133 - 137, The
catch-all else branch in error-handler.interceptor.ts currently overwrites any
resolved backend message by always using
translate.instant('error.unknown.message'); update the else logic to only use
the generic translated message when the local variable errorMessage (the
resolved backend message computed earlier in the function) is empty/undefined,
otherwise pass errorMessage through to this.alertService.alert; locate the
branch around the this.alertService.alert call and conditionally choose between
errorMessage and this.translate.instant('error.unknown.message') so
backend/localized messages are preserved for statuses like 409/422/503.

66-72: ⚠️ Potential issue | 🟠 Major

Prefix these HTTP error lookups with errors..

Line 68 and the status branches below are resolving keys from the root namespace, but the locale files store them under errors (for example src/assets/translations/lt-LT.json). With ngx-translate's default parser, instant('error.auth.type') misses and falls back to the key string, so alerts can render raw keys instead of localized text.

Verification: confirm there is no custom parser remapping these keys, then verify that only the errors.-prefixed paths resolve in the locale JSON.

#!/bin/bash
set -e

# Check whether the app installs a custom ngx-translate parser / missing handler.
rg -n "TranslateParser|MissingTranslationHandler|TranslateModule\\.forRoot" src/app

python3 <<'PY'
import json
from pathlib import Path

def get_value(target, key):
    keys = key.split(".")
    buf = ""
    cur = target
    while keys:
        buf += keys.pop(0)
        if isinstance(cur, dict) and buf in cur and (isinstance(cur[buf], (dict, list)) or not keys):
            cur = cur[buf]
            buf = ""
        elif not keys:
            cur = None
        else:
            buf += "."
    return cur

data = json.loads(Path("src/assets/translations/lt-LT.json").read_text(encoding="utf-8"))
for key in (
    "error.auth.type",
    "errors.error.auth.type",
    "error.bad.request.type",
    "errors.error.bad.request.type",
):
    print(f"{key} => {get_value(data, key)!r}")
PY

Expected result: the unprefixed keys resolve to None, while the errors.-prefixed paths resolve to translated strings.

🔧 Suggested fix pattern
-      const translated = this.translate.instant(globalisationCode, response.error?.errors?.[0] || response.error || {});
-      if (translated !== globalisationCode) {
+      const translationKey = globalisationCode.startsWith('errors.')
+        ? globalisationCode
+        : `errors.${globalisationCode}`;
+      const translated = this.translate.instant(translationKey, response.error?.errors?.[0] || response.error || {});
+      if (translated !== translationKey) {
         errorMessage = translated;
       }
@@
-        type: this.translate.instant('error.auth.type'),
+        type: this.translate.instant('errors.error.auth.type'),

Apply the same prefixing to the other hardcoded status keys as well.

Also applies to: 83-137

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 66 - 72, The
translation lookups are using root keys but your locale JSON nests messages
under "errors", so update all calls that build or pass translation keys to
prefix them with "errors." (e.g., the translate.instant call that uses
globalisationCode and every branch that constructs status-based keys in the
interceptor) so that translate.instant receives "errors.<key>" instead of
"<key>"; locate uses of globalisationCode, translate.instant, and the
response.status handling in error-handler.interceptor.ts and prepend "errors."
to those keys (and to any hardcoded keys in the 83-137 range) ensuring you don't
alter other logic like fallback handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/app/core/http/error-handler.interceptor.ts`:
- Around line 109-114: The branch that handles isClientImage404 should re-throw
the original HttpErrorResponse instead of returning an Observable that emits
null; update the logic in the error handling path (in the interceptor method
where isClientImage404 is checked) to return throwError(() => error) (or rethrow
the error via throw) so downstream subscribers and the imaging service receive
the original HttpErrorResponse rather than a successful null emission.
- Around line 50-64: The current logic sets globalisationCode from
response.error.userMessageGlobalisationCode even after selecting the nested
winner from response.error.errors[0], which overwrites the more specific nested
code; update the conditional that checks
response.error?.userMessageGlobalisationCode so it only assigns to
globalisationCode (and does not change errorMessage) if globalisationCode is
still null/undefined after inspecting response.error.errors[0] — reference the
variables response, globalisationCode, errorMessage and the nested
response.error.errors[0] when making this change.
- Around line 133-137: The catch-all else branch in error-handler.interceptor.ts
currently overwrites any resolved backend message by always using
translate.instant('error.unknown.message'); update the else logic to only use
the generic translated message when the local variable errorMessage (the
resolved backend message computed earlier in the function) is empty/undefined,
otherwise pass errorMessage through to this.alertService.alert; locate the
branch around the this.alertService.alert call and conditionally choose between
errorMessage and this.translate.instant('error.unknown.message') so
backend/localized messages are preserved for statuses like 409/422/503.
- Around line 66-72: The translation lookups are using root keys but your locale
JSON nests messages under "errors", so update all calls that build or pass
translation keys to prefix them with "errors." (e.g., the translate.instant call
that uses globalisationCode and every branch that constructs status-based keys
in the interceptor) so that translate.instant receives "errors.<key>" instead of
"<key>"; locate uses of globalisationCode, translate.instant, and the
response.status handling in error-handler.interceptor.ts and prepend "errors."
to those keys (and to any hardcoded keys in the 83-137 range) ensuring you don't
alter other logic like fallback handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 20fc9573-c71c-411c-ada2-55aeee33e391

📥 Commits

Reviewing files that changed from the base of the PR and between 1d90eb5 and 196f3e0.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json and included by **/*
📒 Files selected for processing (15)
  • src/app/core/http/error-handler.interceptor.ts
  • src/assets/translations/cs-CS.json
  • src/assets/translations/de-DE.json
  • src/assets/translations/en-US.json
  • src/assets/translations/es-CL.json
  • src/assets/translations/es-MX.json
  • src/assets/translations/fr-FR.json
  • src/assets/translations/it-IT.json
  • src/assets/translations/ko-KO.json
  • src/assets/translations/lt-LT.json
  • src/assets/translations/lv-LV.json
  • src/assets/translations/ne-NE.json
  • src/assets/translations/pt-PT.json
  • src/assets/translations/sw-SW.json
  • src/environments/.env.ts
✅ Files skipped from review due to trivial changes (5)
  • src/assets/translations/es-MX.json
  • src/assets/translations/de-DE.json
  • src/assets/translations/cs-CS.json
  • src/assets/translations/en-US.json
  • src/assets/translations/fr-FR.json
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/assets/translations/ne-NE.json
  • src/assets/translations/sw-SW.json
  • src/assets/translations/pt-PT.json
  • src/assets/translations/lv-LV.json
  • src/assets/translations/ko-KO.json
  • src/assets/translations/it-IT.json
  • src/assets/translations/es-CL.json

@saksham869
Copy link
Copy Markdown
Contributor Author

Hi @IOhacker and — I have addressed all 4 review comments:
Nested globalisation Code now takes priority over top-level
All hardcoded keys now use errors. prefix to match translation file structure
Removed duplicate return statements — replaced with throw Error(() => response)
else branch now preserves localized error Message instead of always showing generic text
Please re-review. Thank you!

Copy link
Copy Markdown

@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: 2

♻️ Duplicate comments (1)
src/app/core/http/error-handler.interceptor.ts (1)

43-56: ⚠️ Potential issue | 🟠 Major

Preserve the top-level defaultUserMessage as the fallback.

Responses that only populate top-level userMessageGlobalisationCode / defaultUserMessage still start from developerMessage, so a missing frontend key falls back to technical English instead of the server-localized text.

🔧 Suggested fix
-    let errorMessage = response.error?.developerMessage || response.message;
+    let errorMessage = response.error?.defaultUserMessage || response.error?.developerMessage || response.message;
@@
     if (!globalisationCode && response.error?.userMessageGlobalisationCode) {
       globalisationCode = response.error.userMessageGlobalisationCode;
+      errorMessage = response.error?.defaultUserMessage || errorMessage;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 43 - 56, The
current logic sets errorMessage from developerMessage then overrides with nested
defaultUserMessage, but ignores a top-level defaultUserMessage fallback, causing
developerMessage to be used when a top-level defaultUserMessage exists; update
the initialization and fallback logic in error-handler.interceptor.ts (variables
errorMessage, globalisationCode, response) so errorMessage is initialized as
response.error?.developerMessage || response.error?.defaultUserMessage ||
response.message, and when nested errors are absent or their defaultUserMessage
is missing, fall back to response.error?.defaultUserMessage before using
developerMessage or response.message, while preserving the existing
nested-priority and globalisationCode selection.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/core/http/error-handler.interceptor.ts`:
- Around line 72-89: The OAuth-specific 400 handling is too broad: narrow the
condition (currently using environment.oauth.enabled && status === 400) to only
apply to OAuth/token endpoints by also checking the request URL (e.g.,
request.url or req.url) for the token/auth path (like contains '/token' or the
app's auth route). Update the conditional in error-handler.interceptor (the
interceptor method that inspects status === 401 / 400) so it only shows the auth
alert when status === 400 AND the request URL matches the OAuth token endpoint;
leave the generic 400 branch (errors.error.bad.request) to handle other
validation/business errors.
- Around line 77-80: Replace the brittle check that compares
response.error?.errors?.[0]?.defaultUserMessage to an English string inside the
error handling branch with a check against the stable machine-readable field
response.error?.errors?.[0]?.userMessageGlobalisationCode (as already extracted
earlier in error-handler.interceptor.ts); specifically update the 403 OTP branch
to match the known globalization code (e.g., "error.msg.otp.token.invalid")
instead of the localized defaultUserMessage so the OTP logic in the interceptor
reliably triggers across languages.

---

Duplicate comments:
In `@src/app/core/http/error-handler.interceptor.ts`:
- Around line 43-56: The current logic sets errorMessage from developerMessage
then overrides with nested defaultUserMessage, but ignores a top-level
defaultUserMessage fallback, causing developerMessage to be used when a
top-level defaultUserMessage exists; update the initialization and fallback
logic in error-handler.interceptor.ts (variables errorMessage,
globalisationCode, response) so errorMessage is initialized as
response.error?.developerMessage || response.error?.defaultUserMessage ||
response.message, and when nested errors are absent or their defaultUserMessage
is missing, fall back to response.error?.defaultUserMessage before using
developerMessage or response.message, while preserving the existing
nested-priority and globalisationCode selection.
🪄 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: CHILL

Plan: Pro

Run ID: 7c244537-dbdf-4553-8283-97c3eabb91ba

📥 Commits

Reviewing files that changed from the base of the PR and between 196f3e0 and 80a0e0d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json and included by **/*
📒 Files selected for processing (3)
  • src/app/core/http/error-handler.interceptor.ts
  • src/assets/translations/en-US.json
  • src/environments/.env.ts
💤 Files with no reviewable changes (1)
  • src/environments/.env.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/assets/translations/en-US.json

@saksham869
Copy link
Copy Markdown
Contributor Author

Hi @alberto-art3ch Hernández sir

Merge Conflict Resolved + CodeRabbit Issues Addressed

Rebased onto the latest dev branch to resolve the merge conflict. Additionally addressed both outstanding CodeRabbit review issues:

Changes Made

1. Scoped OAuth 400 to auth endpoints only
Previously, any HTTP 400 response with OAuth enabled would trigger the auth error banner. This has been narrowed to only fire for /oauth/token and /authentication endpoints, preventing legitimate business validation errors (e.g. form field errors) from incorrectly surfacing as authentication failures.

2. OTP check now uses userMessageGlobalisationCode
Replaced the brittle defaultUserMessage English string match for OTP errors with a stable userMessageGlobalisationCode === 'error.msg.otp.token.invalid' check. This ensures the OTP error path works correctly regardless of the server's locale or message wording.

Verification

  • git status — clean working tree, no conflict markers
  • No <<<<<<<, =======, or >>>>>>> markers in the interceptor file
  • Branch successfully rebased and force-pushed

Ready for re-review. Happy to make any further adjustments!

Copy link
Copy Markdown

@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.

Caution

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

⚠️ Outside diff range comments (1)
src/app/core/http/error-handler.interceptor.ts (1)

98-105: ⚠️ Potential issue | 🟡 Minor

Hardcoded English fallback string should be translated.

Lines 100-101 contain the hardcoded string 'Invalid parameters were passed in the request!' which violates i18n guidelines. Additionally, the fallback || this.translate.instant('errors.error.bad.request.message') on line 104 is unreachable since message will always be truthy due to the hardcoded fallback.

🔧 Suggested fix
     } else if (status === 400) {
+      const fallbackMessage = this.translate.instant('errors.error.bad.request.message');
       const message = parameterName
-        ? `[${parameterName}] ${errorMessage || 'Invalid parameters were passed in the request!'}`
-        : `${errorMessage || 'Invalid parameters were passed in the request!'}`;
+        ? `[${parameterName}] ${errorMessage || fallbackMessage}`
+        : errorMessage || fallbackMessage;
       this.alertService.alert({
         type: this.translate.instant('errors.error.bad.request.type'),
-        message: message || this.translate.instant('errors.error.bad.request.message')
+        message: message
       });

Based on learnings: "Use proper i18n variables from ngx-translate/core for all user-facing strings instead of hardcoded text".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` around lines 98 - 105, The
code uses a hardcoded English message and an unreachable fallback; replace the
literal 'Invalid parameters were passed in the request!' with a translated
string and build the message so the alert fallback is reachable: compute a
baseMessage = errorMessage ||
this.translate.instant('errors.error.bad.request.message') and then set message
= parameterName ? `[${parameterName}] ${baseMessage}` : baseMessage, and pass
that message into this.alertService.alert without the extra "||
this.translate.instant(...)" fallback; update the block handling status === 400
(variables: status, parameterName, errorMessage, this.translate.instant,
this.alertService.alert) accordingly.
🧹 Nitpick comments (1)
src/app/core/http/error-handler.interceptor.ts (1)

137-137: Consider using return throwError() for consistency with line 113.

Line 137 uses throw response directly while line 113 uses return throwError(() => response). Both work in a catchError context, but using throwError throughout would be more consistent and idiomatic for RxJS error handling.

♻️ Suggested refactor for consistency
     }
 
-    throw response;
+    return throwError(() => response);
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/core/http/error-handler.interceptor.ts` at line 137, In the
catchError block where the interceptor currently does "throw response", replace
that direct throw with "return throwError(() => response)" to match the pattern
used earlier (line 113) and keep RxJS error handling consistent; look for the
ErrorHandlerInterceptor (or the intercept method / catchError callback) and
change the final throw to a return of throwError(() => response).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/app/core/http/error-handler.interceptor.ts`:
- Around line 98-105: The code uses a hardcoded English message and an
unreachable fallback; replace the literal 'Invalid parameters were passed in the
request!' with a translated string and build the message so the alert fallback
is reachable: compute a baseMessage = errorMessage ||
this.translate.instant('errors.error.bad.request.message') and then set message
= parameterName ? `[${parameterName}] ${baseMessage}` : baseMessage, and pass
that message into this.alertService.alert without the extra "||
this.translate.instant(...)" fallback; update the block handling status === 400
(variables: status, parameterName, errorMessage, this.translate.instant,
this.alertService.alert) accordingly.

---

Nitpick comments:
In `@src/app/core/http/error-handler.interceptor.ts`:
- Line 137: In the catchError block where the interceptor currently does "throw
response", replace that direct throw with "return throwError(() => response)" to
match the pattern used earlier (line 113) and keep RxJS error handling
consistent; look for the ErrorHandlerInterceptor (or the intercept method /
catchError callback) and change the final throw to a return of throwError(() =>
response).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a6641a91-9313-4530-8f2f-94e3a40c1e84

📥 Commits

Reviewing files that changed from the base of the PR and between e52988b and 21e90a4.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json and included by **/*
📒 Files selected for processing (3)
  • src/app/core/http/error-handler.interceptor.ts
  • src/assets/translations/en-US.json
  • src/environments/.env.ts
💤 Files with no reviewable changes (1)
  • src/environments/.env.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/assets/translations/en-US.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants