Skip to content

Adding checks for ok status code in responses#2178

Open
sergey3bv wants to merge 2 commits intogetAlby:masterfrom
sergey3bv:fix/response-ok-check
Open

Adding checks for ok status code in responses#2178
sergey3bv wants to merge 2 commits intogetAlby:masterfrom
sergey3bv:fix/response-ok-check

Conversation

@sergey3bv
Copy link
Contributor

@sergey3bv sergey3bv commented Mar 25, 2026

Should close #327

Summary by CodeRabbit

  • Bug Fixes
    • Improved HTTP status handling across integrations so failed/non-OK responses are surfaced instead of being parsed.
    • Enhanced error messages when external services fail, reducing crashes from malformed responses.
    • Currency/rates fetching now uses a unified data flow with proper error propagation and sensible fallbacks (e.g., SATS) to avoid empty or broken UI states.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 25, 2026

📝 Walkthrough

Walkthrough

Added explicit HTTP status validation across multiple API clients and frontend fetchers: responses are read fully, checked for 200 OK (or res.ok in frontend), logged on failure with status and body, and returned as errors before any JSON parsing occurs.

Changes

Cohort / File(s) Summary
API Response Validation
api/api.go, api/esplora.go
Read response body, verify StatusCode == http.StatusOK; on non-200 log endpoint/URL/status/body and return formatted error instead of attempting JSON unmarshal.
Rebalance Service
api/rebalance.go
Changed success condition for create_order from < 300 to == http.StatusOK; other statuses now treated as errors.
Frontend — Rates Fetching
frontend/src/screens/internal-apps/ZapPlanner.tsx, frontend/src/screens/settings/Settings.tsx
Replaced local fetch logic with SWR (useSWR) and fetchers that throw on non-OK (!res.ok), removing local state-based fetch handlers and moving error handling into SWR paths.
Phoenixd LN Client
lnclient/phoenixd/phoenixd.go
Multiple endpoints now io.ReadAll the body, check resp.StatusCode == http.StatusOK, return fmt.Errorf with status+body on failure, and switch from streaming json.Decoder to json.Unmarshal. Added fmt and io imports.
Swaps / Mempool
swaps/swaps_service.go
Added StatusCode != http.StatusOK checks in mempool/esplora request paths; logs endpoint/URL/status/body and returns error containing response body before deserialization.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through code both near and far,
Checked every response — no hidden scar.
Body read, status true, errors shown,
Now parsers only trust the known. 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding HTTP OK status code checks to API responses throughout the codebase.
Linked Issues check ✅ Passed The PR comprehensively addresses issue #327 by adding HTTP status code validation across all external API calls in the codebase (api, swaps, lnclient, and frontend modules).
Out of Scope Changes check ✅ Passed All changes are directly scoped to adding HTTP OK status code validation before processing response bodies, with no unrelated modifications detected.

✏️ 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
Contributor

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

🧹 Nitpick comments (1)
api/rebalance.go (1)

87-94: Minor inconsistency in log field naming.

The log field uses "statusCode" (camelCase), while other files in this PR use "status_code" (snake_case). Consider using consistent naming across the codebase for easier log querying.

Suggested fix
 	if res.StatusCode != http.StatusOK {
 		logger.Logger.WithFields(logrus.Fields{
 			"request":    newRspCreateOrderRequest,
 			"body":       string(body),
-			"statusCode": res.StatusCode,
+			"status_code": res.StatusCode,
 		}).Error("rebalance create_order endpoint returned non-success code")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@api/rebalance.go` around lines 87 - 94, The log field name is inconsistent:
change the "statusCode" field used in the logger.Logger.WithFields call within
the rebalance create_order response handling (where newRspCreateOrderRequest,
body and res are available) to "status_code" to match the snake_case convention
used elsewhere; update only the key name in that WithFields map so the error log
call and returned error behavior remain unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@api/rebalance.go`:
- Around line 87-94: The log field name is inconsistent: change the "statusCode"
field used in the logger.Logger.WithFields call within the rebalance
create_order response handling (where newRspCreateOrderRequest, body and res are
available) to "status_code" to match the snake_case convention used elsewhere;
update only the key name in that WithFields map so the error log call and
returned error behavior remain unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0657150a-f788-4785-8081-c12cf0bf97d6

📥 Commits

Reviewing files that changed from the base of the PR and between 06b2113 and a8f1d7c.

📒 Files selected for processing (7)
  • api/api.go
  • api/esplora.go
  • api/rebalance.go
  • frontend/src/screens/internal-apps/ZapPlanner.tsx
  • frontend/src/screens/settings/Settings.tsx
  • lnclient/phoenixd/phoenixd.go
  • swaps/swaps_service.go

@sergey3bv
Copy link
Contributor Author

Hey, @michael1011, there is a weird error in CI, could you please take a look?

@michael1011
Copy link

Hey, @michael1011, there is a weird error in CI, could you please take a look?

I don't know why your Mac code signing certificates are not being loaded

@rolznz rolznz requested a review from im-adithya March 25, 2026 12:07
@sergey3bv sergey3bv force-pushed the fix/response-ok-check branch from a8f1d7c to 4792c9e Compare March 25, 2026 13:15
@sergey3bv sergey3bv requested a review from rolznz March 25, 2026 13:15
Copy link
Contributor

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

🧹 Nitpick comments (2)
lnclient/phoenixd/phoenixd.go (1)

110-120: Centralize Phoenixd response decoding and wrap low-level failures.

The new io.ReadAll → status check → json.Unmarshal flow is repeated six times, and the bare err returns still lose which Phoenixd endpoint failed when reads or decodes blow up. A small helper would keep the status gate consistent and preserve endpoint context everywhere.

♻️ Helper sketch
+func decodePhoenixResponse(resp *http.Response, endpoint string, target interface{}) error {
+	body, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return fmt.Errorf("read phoenixd %s response: %w", endpoint, err)
+	}
+	if resp.StatusCode != http.StatusOK {
+		return fmt.Errorf("phoenixd %s returned non-success status: %d %s", endpoint, resp.StatusCode, string(body))
+	}
+	if err := json.Unmarshal(body, target); err != nil {
+		return fmt.Errorf("decode phoenixd %s response: %w", endpoint, err)
+	}
+	return nil
+}

As per coding guidelines, Use error wrapping with fmt.Errorf("context: %w", err) for debugging.

Also applies to: 158-168, 220-230, 267-277, 308-318, 357-367

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

In `@lnclient/phoenixd/phoenixd.go` around lines 110 - 120, Extract the repeated
pattern into a small helper (e.g., phoenixdDecodeResponse(resp *http.Response,
endpoint string, out interface{}) error) that does io.ReadAll, checks
resp.StatusCode==http.StatusOK, and json.Unmarshal into out, and update each
callsite (the /getbalance flow that populates BalanceResponse and the similar
blocks at the other locations) to call this helper; ensure the helper wraps
low-level errors with context using fmt.Errorf("%s read body: %w", endpoint,
err) and fmt.Errorf("%s decode: %w", endpoint, err) and returns a single
formatted error for non-200 statuses like fmt.Errorf("%s returned non-success
status: %d %s", endpoint, resp.StatusCode, string(body)).
frontend/src/screens/settings/Settings.tsx (1)

31-37: Extract the albyRatesFetcher to a shared utility.

Both Settings.tsx (lines 31–37) and ZapPlanner.tsx (lines 119–131) implement identical inline fetchers for the same endpoint using raw fetch(). This duplicates logic and violates the guideline to use the request() helper from frontend/src/utils/request.ts. Extract this to a shared hook or extend request() to support absolute URLs.

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

In `@frontend/src/screens/settings/Settings.tsx` around lines 31 - 37, Duplicate
inline fetch logic for albyRatesFetcher used in Settings.tsx and ZapPlanner.tsx
should be moved to a shared utility and wired to the existing request() helper:
create and export a single function (e.g., albyRatesFetcher or getAlbyRates) in
the shared utils module where request() lives, implement it to call request()
(or extend request() to accept absolute URLs) and perform the same error
handling and typed JSON return, then replace the inline fetch implementations in
both Settings.tsx and ZapPlanner.tsx with imports of that shared function and
remove the duplicated code.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/src/screens/settings/Settings.tsx`:
- Around line 31-37: Duplicate inline fetch logic for albyRatesFetcher used in
Settings.tsx and ZapPlanner.tsx should be moved to a shared utility and wired to
the existing request() helper: create and export a single function (e.g.,
albyRatesFetcher or getAlbyRates) in the shared utils module where request()
lives, implement it to call request() (or extend request() to accept absolute
URLs) and perform the same error handling and typed JSON return, then replace
the inline fetch implementations in both Settings.tsx and ZapPlanner.tsx with
imports of that shared function and remove the duplicated code.

In `@lnclient/phoenixd/phoenixd.go`:
- Around line 110-120: Extract the repeated pattern into a small helper (e.g.,
phoenixdDecodeResponse(resp *http.Response, endpoint string, out interface{})
error) that does io.ReadAll, checks resp.StatusCode==http.StatusOK, and
json.Unmarshal into out, and update each callsite (the /getbalance flow that
populates BalanceResponse and the similar blocks at the other locations) to call
this helper; ensure the helper wraps low-level errors with context using
fmt.Errorf("%s read body: %w", endpoint, err) and fmt.Errorf("%s decode: %w",
endpoint, err) and returns a single formatted error for non-200 statuses like
fmt.Errorf("%s returned non-success status: %d %s", endpoint, resp.StatusCode,
string(body)).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a0932b56-9a72-4b42-af57-95811541ef7a

📥 Commits

Reviewing files that changed from the base of the PR and between a8f1d7c and 4792c9e.

📒 Files selected for processing (7)
  • api/api.go
  • api/esplora.go
  • api/rebalance.go
  • frontend/src/screens/internal-apps/ZapPlanner.tsx
  • frontend/src/screens/settings/Settings.tsx
  • lnclient/phoenixd/phoenixd.go
  • swaps/swaps_service.go
✅ Files skipped from review due to trivial changes (2)
  • swaps/swaps_service.go
  • api/api.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • api/rebalance.go
  • frontend/src/screens/internal-apps/ZapPlanner.tsx

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.

/api/alby/me endpoint returns response with all fields empty

3 participants