From 84cc95a6476ec6d7a86b942aa34a45e96c484bfd Mon Sep 17 00:00:00 2001 From: Quentin David Date: Wed, 5 Nov 2025 14:50:53 +0100 Subject: [PATCH 1/2] fix(payments/generic): EN-392 fixes nil deref if no http resp --- .../connectors/internal/connectors/generic/client/errors.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go b/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go index ea0b9f86c6..20758ca88e 100644 --- a/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go +++ b/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go @@ -12,6 +12,10 @@ var ( ) func wrapError(err error, resp *http.Response) error { + if resp == nil { + return err + } + statusCode := resp.StatusCode if statusCode >= http.StatusBadRequest && statusCode < http.StatusInternalServerError { From a4e18a7cb2dff5d8ce60e1bd58ffb48afcdbc85b Mon Sep 17 00:00:00 2001 From: Quentin David Date: Wed, 5 Nov 2025 15:09:46 +0100 Subject: [PATCH 2/2] Add unreachable server error and add it as a retryable error --- .../internal/connectors/generic/client/errors.go | 7 ++++--- .../internal/connectors/generic/task_fetch_accounts.go | 2 +- .../internal/connectors/generic/task_fetch_balances.go | 2 +- .../connectors/generic/task_fetch_beneficiaries.go | 2 +- .../internal/connectors/generic/task_fetch_transactions.go | 2 +- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go b/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go index 20758ca88e..46182d8102 100644 --- a/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go +++ b/components/payments/cmd/connectors/internal/connectors/generic/client/errors.go @@ -7,13 +7,14 @@ import ( ) var ( - ErrStatusCodeClientError = errors.New("client error") - ErrStatusCodeServerError = errors.New("server error") + ErrStatusCodeClientError = errors.New("client error") + ErrStatusCodeServerError = errors.New("server error") + ErrUnreachableServerError = errors.New("unreachable server") ) func wrapError(err error, resp *http.Response) error { if resp == nil { - return err + return fmt.Errorf("%w: %w", err, ErrUnreachableServerError) } statusCode := resp.StatusCode diff --git a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_accounts.go b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_accounts.go index 3ce74b7f08..cad861c450 100644 --- a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_accounts.go +++ b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_accounts.go @@ -72,7 +72,7 @@ func ingestAccounts( for page := 1; ; page++ { accounts, err := c.ListAccounts(ctx, int64(page), pageSize) if err != nil { - if errors.Is(err, client.ErrStatusCodeServerError) { + if errors.Is(err, client.ErrStatusCodeServerError) || errors.Is(err, client.ErrUnreachableServerError) { return fmt.Errorf("%w: %w", task.ErrRetryable, err) } return err diff --git a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_balances.go b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_balances.go index e5e7c56491..13b41d3f1a 100644 --- a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_balances.go +++ b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_balances.go @@ -38,7 +38,7 @@ func taskFetchBalances(c *client.Client, config *Config, accountID string) task. // retryable error already handled by the client otel.RecordError(span, err) - if errors.Is(err, client.ErrStatusCodeServerError) { + if errors.Is(err, client.ErrStatusCodeServerError) || errors.Is(err, client.ErrUnreachableServerError) { return fmt.Errorf("%w: %w", task.ErrRetryable, err) } diff --git a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_beneficiaries.go b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_beneficiaries.go index cacb34b095..8c04f51969 100644 --- a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_beneficiaries.go +++ b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_beneficiaries.go @@ -67,7 +67,7 @@ func ingestBeneficiaries( for page := 1; ; page++ { beneficiaries, err := c.ListBeneficiaries(ctx, int64(page), pageSize, state.LastCreatedAt) if err != nil { - if errors.Is(err, client.ErrStatusCodeServerError) { + if errors.Is(err, client.ErrStatusCodeServerError) || errors.Is(err, client.ErrUnreachableServerError) { return fetchBeneficiariesState{}, fmt.Errorf("%w: %w", task.ErrRetryable, err) } diff --git a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_transactions.go b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_transactions.go index b1fc77232b..0d35f29174 100644 --- a/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_transactions.go +++ b/components/payments/cmd/connectors/internal/connectors/generic/task_fetch_transactions.go @@ -72,7 +72,7 @@ func ingestTransactions( for page := 1; ; page++ { transactions, err := c.ListTransactions(ctx, int64(page), pageSize, state.LastUpdatedAt) if err != nil { - if errors.Is(err, client.ErrStatusCodeServerError) { + if errors.Is(err, client.ErrStatusCodeServerError) || errors.Is(err, client.ErrUnreachableServerError) { return fetchTransactionsState{}, fmt.Errorf("%w: %w", task.ErrRetryable, err) }