antiwork/gumroad · error · ResponseError

${data.error}

Error message

${data.error}

What it means

addToWishlist (app/javascript/data/wishlists.ts:54-87) POSTs a wishlist_product and, on !response.ok, decodes the body as {error: string} and throws ResponseError(data.error) — the server's message reaches the user. Expect 422-class refusals: product not purchasable/available, invalid quantity or recurrence, product already in the wishlist, or wishlist not editable by this user; also 401/403/404 with an error-bearing body. Called from the product share section (components/Product/ShareSection.tsx:60).

Source

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

  quantity: number | null;
}) => {
  const response = await request({
    method: "POST",
    url: Routes.wishlist_products_path(wishlistId),
    accept: "json",
    data: {
      wishlist_product: {
        product_id: productId,
        option_id: optionId,
        recurrence,
        rent,
        quantity,
      },
    },
  });
  if (!response.ok) {
    const data = typia.assert<{ error: string }>(await response.json());
    throw new ResponseError(data.error);
  }
};

export const updateWishlist = async ({
  id,
  ...wishlist
}: {
  id: string;
  name?: string;
  description?: string | null;
  discover_opted_out?: boolean;
}) => {
  const response = await request({
    method: "PUT",
    url: Routes.wishlist_path(id),
    accept: "json",
    data: { wishlist },
  });

View on GitHub (pinned to afeacbd394)

Solutions

  1. Read e.message — the server states the refusal (availability, quantity, duplicates)
  2. Refresh the product page and retry so availability and options are current
  3. Pick a different wishlist when the error says the current one isn't editable
  4. Note the trap: if the error body isn't exactly {error: string}, typia.assert throws its own error — guard the parse (see exampleFix)

Example fix

// before
const data = typia.assert<{ error: string }>(await response.json());
throw new ResponseError(data.error);

// after — don't let a non-envelope error body crash the error path
const body: unknown = await response.json().catch(() => null);
throw new ResponseError(typia.is<{ error: string }>(body) ? body.error : "Could not add to wishlist.");
Defensive patterns

Strategy: try-catch

Validate before calling

const addable = (p: { productId: string; quantity: number | null }) =>
  p.productId !== "" && (p.quantity === null || p.quantity > 0);
if (!addable({ productId, quantity })) return showError("Pick a product and a valid quantity.");

Type guard

import typia from "typia";
const hasErrorString = typia.is<{ error: string }>;

Try / catch

try {
  await addToWishlist({ wishlistId, productId, optionId, recurrence, rent, quantity });
} catch (e) {
  assertResponseError(e);
  showAlert(e.message, "error"); // server's refusal: not purchasable, bad quantity, duplicate
}

Prevention

When it happens

Trigger: Clicking 'Add to wishlist' on a product page for a product that is unpublished, expired, or not purchasable; adding with quantity 0 or a recurrence the product doesn't support; adding to a wishlist the user can no longer edit; adding the same product twice where duplicates are refused.

Common situations: Stale buy buttons on cached product pages after a seller unpublishes; variant/option combinations removed by the seller; wishlists deleted in another tab; tests stubbing the route without an error field.

Related errors


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