electric icon indicating copy to clipboard operation
electric copied to clipboard

feat: Add structured error codes for stack unavailability

Open KyleAMathews opened this issue 1 month ago • 2 comments

Summary

Adds a machine-readable error code to all 503 responses when the Electric stack cannot respond to requests. This enables clients to programmatically detect stack unavailability without parsing error message strings.

Changes

  • New Module: Electric.Shapes.Api.ErrorCode with single STACK_UNAVAILABLE error code
  • Updated Response: Added error_code field to Response struct
  • Updated StatusMonitor: Now returns structured error information with both message and error code
  • Updated API error handling: All stack unavailability errors now include error code and are marked as known errors
  • Simple tests: Test file covering error code functionality

Error Response Format

Before

{
  "message": "Timeout waiting for database connection pool (snapshot) to be ready"
}

After

{
  "message": "Timeout waiting for database connection pool (snapshot) to be ready",
  "code": "STACK_UNAVAILABLE"
}

Design Decisions

  • Single error code: All stack unavailability scenarios use the same STACK_UNAVAILABLE code. The message already provides component-specific details.
  • No retry metadata: Retry timing is handled by the RETRY-AFTER header (being added in another PR). The error code is only for high-level categorization.
  • Simple and clean: Just adds a code field - no additional metadata like component, retryable, or backoff_ms.

Benefits

For Clients

  • Programmatic detection: Reliably detect stack unavailability without string parsing
  • Better error handling: Can differentiate between stack unavailable (503 with code) vs other errors (503 without code)
  • Future-proof: Easy to add more error codes for other scenarios (client errors, etc.)

For Operations

  • Better monitoring: Track stack unavailability errors separately from other 503s
  • Cleaner metrics: Count STACK_UNAVAILABLE errors as a single category

For Support

  • Clearer bug reports: Users can provide error code
  • Consistent categorization: All stack unavailability issues have the same code

Example Client Usage

async function fetchShape(url: string): Promise<Response> {
  const response = await fetch(url);

  if (response.status === 503) {
    const error = await response.json();

    if (error.code === 'STACK_UNAVAILABLE') {
      // Stack is unavailable - check RETRY-AFTER header for retry timing
      const retryAfter = response.headers.get('retry-after');
      console.log(`Stack unavailable: ${error.message}`);
      console.log(`Retry after: ${retryAfter}`);
      
      // Implement retry logic based on RETRY-AFTER header
      // ...
    }
  }

  return response;
}

Backwards Compatibility

Fully backwards compatible - all changes are additive:

  • Error messages unchanged
  • HTTP status codes unchanged
  • Existing timeout_message/1 function preserved
  • Error code is an additional field

Clients that don't check for error codes will continue to work using HTTP status codes and message parsing.

Testing

  • All existing tests pass
  • New test file covers error code functionality
  • Updated existing test to verify error code presence in responses
  • Verified error code appears in all stack unavailability scenarios

Test Plan

  • [x] Verify STACK_UNAVAILABLE code is returned in all stack 503 responses
  • [x] Verify error code field is only added when error_code is provided
  • [x] Test StatusMonitor timeout error detection
  • [x] Verify backwards compatibility (existing tests still pass)
  • [ ] Manual testing of various stack unavailability scenarios (can be done during review/staging)

🤖 Generated with Claude Code

KyleAMathews avatar Oct 30 '25 10:10 KyleAMathews

Codecov Report

:x: Patch coverage is 63.15789% with 7 lines in your changes missing coverage. Please review. :white_check_mark: Project coverage is 69.60%. Comparing base (ec24e64) to head (69882e1). :warning: Report is 76 commits behind head on main.

Files with missing lines Patch % Lines
...ckages/sync-service/lib/electric/status_monitor.ex 0.00% 7 Missing :warning:
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3357      +/-   ##
==========================================
+ Coverage   67.00%   69.60%   +2.60%     
==========================================
  Files         169      179      +10     
  Lines        8786     9726     +940     
  Branches      106      334     +228     
==========================================
+ Hits         5887     6770     +883     
- Misses       2898     2954      +56     
- Partials        1        2       +1     
Flag Coverage Δ
elixir 66.69% <63.15%> (-0.03%) :arrow_down:
elixir-client 74.47% <ø> (+0.52%) :arrow_up:
packages/experimental 87.73% <ø> (ø)
packages/react-hooks 86.48% <ø> (ø)
packages/typescript-client 94.41% <ø> (?)
packages/y-electric 55.12% <ø> (ø)
postgres-140000 65.67% <63.15%> (-0.21%) :arrow_down:
postgres-150000 65.73% <63.15%> (-0.14%) :arrow_down:
postgres-170000 65.81% <63.15%> (+0.05%) :arrow_up:
postgres-180000 65.68% <63.15%> (-0.07%) :arrow_down:
sync-service 65.92% <63.15%> (-0.08%) :arrow_down:
typescript 87.32% <ø> (+14.92%) :arrow_up:
unit-tests 69.60% <63.15%> (+2.60%) :arrow_up:

Flags with carried forward coverage won't be shown. Click here to find out more.

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

codecov[bot] avatar Oct 30 '25 10:10 codecov[bot]

Deploy Preview for electric-next ready!

Name Link
Latest commit 69882e1bf385126eee9e53d4d7e63289a79702d0
Latest deploy log https://app.netlify.com/projects/electric-next/deploys/69034dcf7ea5820008605f58
Deploy Preview https://deploy-preview-3357--electric-next.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

netlify[bot] avatar Oct 30 '25 10:10 netlify[bot]

Closing this PR and converting it to issue #3469 for further discussion and implementation planning.

KyleAMathews avatar Nov 19 '25 16:11 KyleAMathews