Skip to content

fix(ucs): use NO_ERROR_CODE fallback when connector error code is absent#13095

Open
AmitsinghTanwar007 wants to merge 2 commits into
mainfrom
autofix/cybersource-psync-17477
Open

fix(ucs): use NO_ERROR_CODE fallback when connector error code is absent#13095
AmitsinghTanwar007 wants to merge 2 commits into
mainfrom
autofix/cybersource-psync-17477

Conversation

@AmitsinghTanwar007

Copy link
Copy Markdown
Contributor

Summary

When the UCS psync path returns a connector HTTP error (4xx/5xx) with no connector-specific error code, decode_connector_error_response was falling back to the gRPC discriminator string "CONNECTOR_ERROR_RESPONSE" instead of "No error code". This caused a shadow-validation diff on response.Err.code between the HS direct path and the UCS path for connectors (e.g. cybersource psync) that return error responses without a specific error code.

Diff signature: router.valueDiff:response.Err.code
Layer: HS→UCS mapping (hyperswitch_interfaces/src/unified_connector_service/transformers.rs)
Flow: cybersource / psync

Root cause

When a connector returns a 4xx error with no specific error code:

  1. HS direct path → build_error_responsecode = "No error code" (the NO_ERROR_CODE constant)
  2. UCS path → same build_error_responsecode = "No error code"ForeignFrom<&ErrorResponse>: since code == NO_ERROR_CODE AND reason == None, has_connector_details = falseerror_info = None in the gRPC ConnectorError message → HS decode_connector_error_response: connector_details is None → the .unwrap_or_else(|| connector_error.error_code.clone()) fallback returned "CONNECTOR_ERROR_RESPONSE"wrong

The fix changes the fallback from connector_error.error_code.clone() to crate::consts::NO_ERROR_CODE.to_string() so both paths surface "No error code" when the connector provides no specific code.

Verification

Verified by source-parity analysis (cybersource TLS-blocked locally):

Before fix: decode_connector_error_response fallback → code = "CONNECTOR_ERROR_RESPONSE" → HS shadow diff: response.Err.code = "No error code" (HS) vs "CONNECTOR_ERROR_RESPONSE" (UCS)

After fix: decode_connector_error_response fallback → code = "No error code" → both paths agree → no_diff

Unit tests added:

  • decode_prefers_connector_details_code: when connector_details.code = Some("INVALID_REQUEST") → surfaced code is "INVALID_REQUEST"
  • decode_falls_back_to_no_error_code_when_connector_code_absent: when error_info = None → surfaced code is "No error code"

Closes #13094

@AmitsinghTanwar007 AmitsinghTanwar007 requested a review from a team as a code owner June 30, 2026 14:35
@semanticdiff-com

semanticdiff-com Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review changes with  SemanticDiff

@AmitsinghTanwar007 AmitsinghTanwar007 requested review from a team as code owners June 30, 2026 14:41
Amit and others added 2 commits June 30, 2026 20:14
When decode_connector_error_response receives a ConnectorError with no
connector_details (error_info=None), it previously fell back to the gRPC
discriminator "CONNECTOR_ERROR_RESPONSE" — causing a shadow-validation diff
on response.Err.code. Changed fallback to NO_ERROR_CODE ("No error code") to
match the HS direct path behaviour.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@AmitsinghTanwar007 AmitsinghTanwar007 force-pushed the autofix/cybersource-psync-17477 branch from ab8b98e to 5d379e2 Compare June 30, 2026 14:44
@XyneSpaces

Copy link
Copy Markdown

⚠️ Error code fallback logic may mask connector-specific failures

The change from connector_error.error_code.clone() to crate::consts::NO_ERROR_CODE.to_string() as a fallback when connector_details is absent may mask legitimate connector errors in logging/monitoring.

Consider preserving the original error context even when falling back:

let error_code = connector_details
    .as_ref()
    .map(|d| d.error_code.clone())
    .unwrap_or_else(|| {
        logger::warn!("Connector error code unavailable, using NO_ERROR_CODE fallback");
        crate::consts::NO_ERROR_CODE.to_string()
    });

This ensures operational visibility into when connectors return HTTP errors without specific error codes.

@XyneSpaces

Copy link
Copy Markdown

📝 Code Review: UCS Error Code Fallback

This is a straightforward fix ensuring consistent error code behavior between UCS and direct HS paths.

✅ Change Analysis

The modification replaces a fallback that would return "CONNECTOR_ERROR_RESPONSE" with the standardized "No error code" constant. This improves consistency across the codebase.

💡 Minor Suggestion

Consider adding a brief comment explaining why NO_ERROR_CODE is preferred over the connector's raw error response, for future maintainers.

🟢 LGTM

Simple, correct fix with no blocking issues.

@XyneSpaces

Copy link
Copy Markdown

💡 The NO_ERROR_CODE and NO_ERROR_MESSAGE constants used as fallbacks should have corresponding metrics/alerts when triggered. Consider adding a counter metric to track how frequently the fallback is used, as this indicates incomplete error-code mapping.

Also verify that downstream systems (Control Center, analytics) handle these sentinel values gracefully.

@XyneSpaces

Copy link
Copy Markdown

[nit] This PR is a clean, targeted fix. The change from connector_error.error_code.clone() to NO_ERROR_CODE correctly prevents leaking the internal gRPC discriminator "CONNECTOR_ERROR_RESPONSE" to end users. Tests cover both branches appropriately. No changes requested.

@AmitsinghTanwar007 AmitsinghTanwar007 force-pushed the autofix/cybersource-psync-17477 branch from 5d379e2 to c09924d Compare July 1, 2026 11:23
@XyneSpaces

Copy link
Copy Markdown

💡 Test coverage is good

The unit tests added for the NO_ERROR_CODE fallback are well-structured and cover both the happy path (connector provides code) and fallback path. Good practice adding these tests alongside the fix.

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.

fix(ucs): UCS psync path surfaces CONNECTOR_ERROR_RESPONSE instead of No error code when connector provides no specific error code

2 participants