Skip to content

useBountyStatus: a transient fetch failure mid-session silently swaps the live bounty for static fallbackBounty and fires a false onStatusChange #571

Description

@chonilius

Problem

useBountyStatus polls with fetchBounty(bountyId, fallbackBounty) from src/lib/api.ts:

export async function fetchBounty(id, fallback) {
  try {
    const raw = await request<RawBounty>(`/bounties/${id}`);
    return { data: adaptBounty(raw), source: "live" };
  } catch {
    return { data: fallback, source: "mock" };
  }
}

That's right for the first server-side render (#1). Inside a polling loop, though, it means any single failed poll, such as a timeout, a 5xx or a brief network drop, resolves successfully with the static fallbackBounty snapshot the page was rendered with.

useSmartPolling then compares it with the previous live data using useBountyStatus's compareFn (status plus claimedBy):

  1. The data regresses. If the bounty moved on, for example open → claimed live, the fallback still says open. The compare sees a change, so data is replaced by the stale snapshot: the badge jumps back to "Open" and source flips to mock.
  2. onStatusChange fires with the stale status. Parents act on a transition that never happened. When the next poll succeeds, it fires again with the real status.
  3. The error UI is unreachable. fetchBounty never throws, so useSmartPolling's error is never set. BountyStatus's "Failed to load status / Retry" branch can never render, and ClaimButton's 2s claim-race polling can briefly show a claimed bounty as claimable again.

Suggested fix

  • Once live data has been received, a failed poll should keep the last live data and surface an error or stale flag, instead of replacing it with fallbackBounty.
  • For example: let the polling fetchFn use a throwing variant, such as the underlying request()/adapter, and apply the fallback only when there's no previous live result.
  • Add a test covering: live data (claimed), then a failed poll, and assert the status is still claimed, onStatusChange isn't called, and error is set.

Related: #1 (live vs mock distinction), #46.

Activity

  1. added
    bugSomething isn't working
    help wantedExtra attention is needed
    very hardVery difficult task, expert-level effort required
    Stellar WaveIssues in the Stellar wave program
    on Sep 27, 2026
  2. drips-wave commented on Sep 27, 2026

    @drips-wave

    @chonilius This issue could not be added to the Stellar Wave Program because the per-repo points budget would be exceeded (25000 / 25000 points already used). The label has been automatically removed.

    The budget resets at the end of each Wave. You can review the remaining budget for your repos on the Orgs & Repos page.

    ℹ️ Learn more about points budgets

  3. rupesh-kumar-sah commented on Oct 2, 2026

    @rupesh-kumar-sah

    Greetings @maintainers,

    I would like to take on and implement this issue: useBountyStatus: a transient fetch failure mid-session silently swaps the live bounty for static fallbackBounty and fires a false onStatusChange.

    Technical Implementation Roadmap:

    1. Deep Codebase Audit: Inspect current architecture and data flows in MergeFi/frontend to design an optimal, idiomatic solution.
    2. Core Modular Implementation: Implement useBountyStatus: a transient fetch failure mid-session silently swaps the live bounty for static fallbackBounty and fires a false onStatusChange with clean separation of concerns and robust error handling.
    3. Comprehensive Automated Test Matrix: Add end-to-end integration and unit tests covering positive execution and edge failure modes.
    4. Production CI Verification: Ensure all linters, formatting checks, and GitHub Actions workflows pass with 100% green status.

    I have worked extensively on similar architectures and can deliver this cleanly within 24 hours. Please assign to me!

  4. Ranjeet2063 commented on Oct 2, 2026

    @Ranjeet2063

    Hi,

    I have experience with similar implementations and would like to take this on.

    Technical outline:

    1. Inspect repository architecture in MergeFi/frontend for an idiomatic solution.
    2. Implement the feature/fix with clean modular separation and robust error handling.
    3. Add comprehensive unit and integration test coverage for all edge cases.
    4. Verify that all linters, formatting, and CI checks pass cleanly.

    Ready to implement immediately upon assignment. Please feel free to assign!

  5. Proxima84-code commented on Oct 6, 2026

    @Proxima84-code

    Submitted fix and unit tests covering transient poll failure and mock fallback behavior via #584.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is neededvery hardVery difficult task, expert-level effort required

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions