antiwork/gumroad · warning · ResponseError

${responseData.message}

Error message

${responseData.message}

What it means

verifyCustomDomain POSTs the domain and product id to custom_domain_verifications_path and expects { success, message }. On success:false the server's message (DNS instructions, propagation status) is thrown as the ResponseError message and rendered into the fieldset's failure state. The catch's assertResponseError re-throws non-ResponseError shapes (e.g. TypiaError on an unexpected body), which would crash the component rather than show the failure state.

Source

Thrown at app/javascript/components/CustomDomain.tsx:64

      timeout = setTimeout(() => {
        setVerificationInfo((prevState) => ({ ...prevState, buttonState: "initial" }));
      }, 2000);
    }
    return () => clearTimeout(timeout);
  }, [verificationInfo.buttonState]);

  const verifyCustomDomain = asyncVoid(async () => {
    setVerificationInfo({ buttonState: "verifying", state: "verifying", message: "" });

    try {
      const response = await request({
        method: "POST",
        accept: "json",
        url: Routes.custom_domain_verifications_path(),
        data: { domain: customDomain, product_id: productId },
      });
      const responseData = typia.assert<{ success: boolean; message: string }>(await response.json());
      if (!responseData.success) throw new ResponseError(responseData.message);
      setVerificationInfo({ buttonState: "success", state: "success", message: responseData.message });
    } catch (e) {
      assertResponseError(e);
      setVerificationInfo({ buttonState: "failure", state: "failure", message: e.message });
    }
  });

  return (
    <Fieldset
      state={
        verificationInfo.state === "success" ? "success" : verificationInfo.state === "failure" ? "danger" : undefined
      }
    >
      <FieldsetTitle>
        <Label htmlFor={uid}>{label}</Label>
        {includeLearnMoreLink ? (
          <a href="/help/article/153-setting-up-a-custom-domain" target="_blank" rel="noreferrer">
            Learn more

View on GitHub (pinned to afeacbd394)

Solutions

  1. Read the failure message — it is the server's diagnosis of the DNS state, usually naming the missing/wrong record.
  2. Check the DNS yourself: dig CNAME subdomain.example.com (or the TXT record) against the value the setup instructions gave.
  3. Wait out DNS TTL (minutes to hours) and verify again — propagation, not breakage, is the most common cause.
  4. If the domain is on another account, it must be released there first.
  5. Disable the registrar's proxy for the record during verification if it masks the target.

Example fix

// before
} catch (e) {
  assertResponseError(e);
  setVerificationInfo({ buttonState: 'failure', state: 'failure', message: e.message });
}

// after — a body-shape surprise should land in the failure state, not crash the component
} catch (e) {
  const message = e instanceof ResponseError ? e.message : 'Verification failed. Please try again.';
  setVerificationInfo({ buttonState: 'failure', state: 'failure', message });
}
Defensive patterns

Strategy: validation

Validate before calling

const DOMAIN = /^(?!-)[a-z0-9-]{1,63}(?<!-)(\.[a-z0-9-]{1,63})+$/i;

if (!DOMAIN.test(customDomain.trim())) {
  setVerificationInfo({ buttonState: 'failure', state: 'failure', message: 'Enter a valid domain, e.g. shop.example.com.' });
  return;
}

Type guard

const isVerificationResult = (v: unknown): v is { success: boolean; message: string } =>
  typeof v === 'object' && v !== null &&
  typeof (v as { success?: unknown }).success === 'boolean' &&
  typeof (v as { message?: unknown }).message === 'string';

Try / catch

try {
  await verifyCustomDomain();
} catch (e) {
  const message = e instanceof ResponseError ? e.message : 'Verification failed. Please try again.';
  setVerificationInfo({ buttonState: 'failure', state: 'failure', message });
}

Prevention

When it happens

Trigger: The domain's CNAME/TXT records not yet propagated or pointing at the wrong target; domain already verified on another Gumroad account; apex domain submitted where a subdomain is required — each returns success:false with a message describing the DNS problem.

Common situations: Seller clicks Verify seconds after adding the record (TTL not elapsed); typo in the CNAME target; registrar defaulting to an A record; Cloudflare proxying (orange cloud) hiding the CNAME value from verification.

Related errors


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