antiwork/gumroad · error · ResponseError

Something went wrong.

Error message

Something went wrong.

What it means

unfollowWishlist (app/javascript/data/wishlists.ts:146-153) DELETEs Routes.wishlist_followers_path(wishlistId) and throws generic ResponseError ('Something went wrong.') on !response.ok — unlike followWishlist it does not parse the error body. With 5xx/429/network handled inside request(), this is a 4xx: 404 (not following anymore — follower record gone, or wishlist deleted), 401 (expired session), 403. Called from FollowButton.tsx:38 (toggle) and the Following page (pages/Wishlists/Following/Index.tsx:43).

Source

Thrown at app/javascript/data/wishlists.ts:152

export const followWishlist = async ({ wishlistId }: { wishlistId: string }) => {
  const response = await request({
    method: "POST",
    url: Routes.wishlist_followers_path(wishlistId),
    accept: "json",
  });
  if (!response.ok) {
    const data = typia.assert<{ error: string }>(await response.json());
    throw new ResponseError(data.error);
  }
};

export const unfollowWishlist = async ({ wishlistId }: { wishlistId: string }) => {
  const response = await request({
    method: "DELETE",
    url: Routes.wishlist_followers_path(wishlistId),
    accept: "json",
  });
  if (!response.ok) throw new ResponseError();
};

export const fetchWishlists = async (ids: string[]) => {
  const response = await request({
    method: "GET",
    url: Routes.wishlists_path({ ids }),
    accept: "json",
  });
  if (!response.ok) throw new ResponseError();
  return typia.assert<CardWishlist[]>(await response.json());
};

View on GitHub (pinned to afeacbd394)

Solutions

  1. Refresh so the following state comes from the server, then only show Unfollow when truly following
  2. Treat 'already unfollowed' (404) as success and update local state
  3. Disable the toggle while the unfollow is in flight
  4. Check the DELETE's status in the network tab to distinguish 404/401/403

Example fix

// components/Wishlist/FollowButton.tsx — converge on failure instead of only toasting
try {
  await unfollowWishlist({ wishlistId });
} catch (e) {
  assertResponseError(e);
  setIsFollowing(false); // record may already be gone; align with server
  showAlert(e.message, "error");
}
Defensive patterns

Strategy: try-catch

Validate before calling

const canUnfollow = (isFollowing: boolean) => isFollowing;
if (!canUnfollow(isFollowing)) return; // no follower record to DELETE — the call would 404

Type guard

const isResponseError = (e: unknown): e is ResponseError => e instanceof ResponseError;

Try / catch

try {
  await unfollowWishlist({ wishlistId });
} catch (e) {
  assertResponseError(e);
  setIsFollowing(false); // record may already be gone; align local state with server
  showAlert(e.message, "error");
}

Prevention

When it happens

Trigger: Clicking Unfollow when the follower record was already removed (double click, stale 'following' badge, unfollowed in another tab); unfollowing a wishlist deleted by its owner (404); session expiring before the click (401).

Common situations: Following-list pages open across tabs; follow toggles racing on slow networks; state desync where the button shows Following but the server already removed the record; tests unfollowing twice.

Related errors


AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21). Data as JSON: /api/errors/5126a603ddc7639d. Report an issue: GitHub.