Skip to content

fix(miner-ui): portfolio queue release/requeue action failures are silently swallowed #6090

Description

@JSONbored

Context

apps/loopover-miner-ui/src/routes/portfolio.tsx's runQueueAction (~line 183) wraps the release/requeue button handlers:

const runQueueAction = (action: () => Promise<unknown>) => {
  setActionPending(true);
  void action().then(() => {
    setRefreshKey((key) => key + 1);
    refreshItems();
    setActionPending(false);
  });
};

releaseItem/requeueItem (lib/portfolio-queue-actions.ts) resolve to a typed PortfolioQueueActionResult — either {ok: true, entry} or {ok: false, error} — and real failure modes exist and are tested at the client-library level (e.g. a 409 queue_entry_not_in_progress/queue_entry_not_requeuable). But runQueueAction types its callback as Promise<unknown> and discards the resolved value entirely: on failure it still just re-enables the button and silently refreshes the list, with no user-visible error.

This is the one inconsistent half of a single feature (#4857, "Add real actions to the miner-ui"): the governor half in the sibling route ledgers.tsx handles this correctly — runGovernorAction threads the resolved GovernorPauseStateResult into pauseState, which GovernorControlSection renders via its !result.ok error branch. The portfolio-queue half never got the equivalent treatment. portfolio-queue-actions.test.tsx's only PortfolioPage-level action test (~lines 98-118) only exercises the success case, confirming the failure path is untested as well as unhandled.

Requirements

  • Change runQueueAction to thread the resolved PortfolioQueueActionResult through to component state (mirroring runGovernorAction's pattern exactly), instead of discarding it.
  • Render the {ok: false, error} case visibly to the operator — reuse GovernorControlSection's existing error-rendering convention (role="alert", same visual treatment) rather than inventing a new one.
  • On failure, do NOT silently refresh the list as if the action succeeded — only refresh/advance refreshKey on {ok: true}.
  • Preserve the existing success-path behavior (refresh + actionPending reset) exactly as-is.

Deliverables

  • runQueueAction in portfolio.tsx threads the real result instead of discarding it
  • Failure case renders a visible, accessible error message to the operator
  • List refresh only happens on success, not on failure
  • Test: a failing release/requeue action (409 or other error) renders the error and does NOT advance refreshKey/re-fetch as if it succeeded — extend portfolio-queue-actions.test.tsx's existing PortfolioPage-level test, which currently only covers the success case

Test Coverage Requirements

99%+ patch coverage (branch-counted), including the new failure-rendering branch.

Expected Outcome

A failed portfolio-queue release/requeue action (e.g. the entry already moved out of in_progress) shows a clear, visible error to the operator instead of silently doing nothing — matching the governor pause/resume controls' existing error-handling behavior in the sibling route.

Links & Resources

  • apps/loopover-miner-ui/src/routes/portfolio.tsx (runQueueAction, the bug)
  • apps/loopover-miner-ui/src/routes/ledgers.tsx (runGovernorAction, the pattern to mirror)
  • apps/loopover-miner-ui/src/lib/portfolio-queue-actions.ts (PortfolioQueueActionResult type, real failure modes)
  • apps/loopover-miner-ui/src/portfolio-queue-actions.test.tsx (existing success-only PortfolioPage action test to extend)
  • #4857 (the PR that added both the governor and portfolio-queue action surfaces)

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:bugGittensor-scored bug fix — scores a 0.05x multiplier.help wantedExtra attention is needed

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions