antiwork/gumroad · error · ResponseError

Sorry, something went wrong. Please try again.

Error message

Sorry, something went wrong. Please try again.

What it means

fetchMediaUrls asks the server for streamable media URLs for a purchased file via GET url_redirect_media_urls_path(purchaseInfo.token, { file_ids }). A non-2xx response (4xx — 5xx/429 were already converted inside request()) throws a bare ResponseError, which the callers around lines 334/725 catch and report as 'Sorry, something went wrong. Please try again.'.

Source

Thrown at app/javascript/components/Download/FileList.tsx:213

    <TrackClick eventName="download_click" file={file}>
      <NavigationButton href={downloadUrl}>Download</NavigationButton>
    </TrackClick>
  ) : null;
  const streamUrl = file.stream_url;
  const externalLinkUrl = file.external_link_url;
  const mediaUrls = allMediaUrls[file.id] ?? [];
  const fetchMediaUrls = async () => {
    try {
      if (isFetchingMediaUrls) return;
      setIsFetchingMediaUrls(true);
      const response = await request({
        url: Routes.url_redirect_media_urls_path(purchaseInfo.token, {
          params: { file_ids: [file.id] },
        }),
        method: "GET",
        accept: "json",
      });
      if (!response.ok) throw new ResponseError();
      const urls = typia.assert<Record<string, string[]>>(await response.json());
      if (!urls[file.id]?.length) throw new ResponseError();
      setAllMediaUrls((prev) => ({ ...prev, ...urls }));
    } finally {
      setIsFetchingMediaUrls(false);
    }
  };

  const playAudio = () => {
    if (!isShowingAudioDrawer) setPlayingAudioForId(file.id);
    if (isShowingAudioDrawer && playingAudioForId === file.id) setPlayingAudioForId(null);
    toggleAudioDrawer();
  };

  if (isMobileAppWebView && FileUtils.isAudioExtension(file.extension)) {
    return <MobileAppAudioFileRow file={file} />;
  }

View on GitHub (pinned to afeacbd394)

Solutions

  1. Check the Network tab for the media-urls request: 401/404 points at the token, 422 at file eligibility.
  2. If the token expired, send the buyer through the original download email/link again to mint a fresh token.
  3. Verify the purchase still exists and is not refunded/disputed in the admin console.
  4. Confirm the requested file id actually belongs to the purchase and is a streamable type.
  5. Surface a more specific message than the generic string when the status is known to be an auth problem.

Example fix

// before
if (!response.ok) throw new ResponseError();

// after
if (!response.ok) throw new ResponseError(response.status === 401 ? 'This download link has expired. Use the link from your email.' : 'Could not load this file. Please try again.');
Defensive patterns

Strategy: try-catch

Validate before calling

const looksLikeDownloadToken = (token: string | undefined): token is string =>
  typeof token === 'string' && token.length > 10 && /^[A-Za-z0-9_-]+$/.test(token);

if (!looksLikeDownloadToken(purchaseInfo?.token)) {
  showAlert('This download link is not valid. Use the link from your receipt email.', 'error');
  return;
}

Type guard

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

Try / catch

try {
  await fetchMediaUrls();
} catch (e) {
  assertResponseError(e);
  showAlert(e.message, 'error');
}

Prevention

When it happens

Trigger: The purchase token in the URL is expired, revoked, or malformed (401/404); the file id is not streamable media (422); the download session was invalidated (refund/chargeback) — any 4xx from the media-urls endpoint hits this throw.

Common situations: Buyer returns to an old download link whose token expired; purchase refunded so access was revoked; file replaced with a non-streamable type while the page was open; direct navigation with a truncated token (mailer line-wrap).

Related errors


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