Stirling-Tools/Stirling-PDF · warning · Error

No valid license found. Please purchase a license before acc

Error message

No valid license found. Please purchase a license before accessing the billing portal.

What it means

Thrown by AdminPlanSection.handleManageClick when the user's license is absent, falsy, or 'NORMAL' (free tier). Only PRO or ENTERPRISE licenses are permitted to open the billing portal — the portal is for managing paid subscriptions, not for free-tier users.

Source

Thrown at frontend/editor/src/proprietary/components/shared/config/configSections/AdminPlanSection.tsx:66

    { value: "gbp", label: "British pound (GBP, £)" },
    { value: "usd", label: "US dollar (USD, $)" },
    { value: "eur", label: "Euro (EUR, €)" },
    { value: "cny", label: "Chinese yuan (CNY, ¥)" },
    { value: "inr", label: "Indian rupee (INR, ₹)" },
    { value: "brl", label: "Brazilian real (BRL, R$)" },
    { value: "idr", label: "Indonesian rupiah (IDR, Rp)" },
  ];

  const handleManageClick = useCallback(async () => {
    // Block access if login is disabled
    if (!validateLoginEnabled()) {
      return;
    }

    try {
      // Only allow PRO or ENTERPRISE licenses to access billing portal
      if (!licenseInfo?.licenseType || licenseInfo.licenseType === "NORMAL") {
        throw new Error(
          "No valid license found. Please purchase a license before accessing the billing portal.",
        );
      }

      if (!licenseInfo?.licenseKey) {
        throw new Error("License key missing. Please contact support.");
      }

      // Create billing portal session with license key
      const response = await licenseService.createBillingPortalSession(
        window.location.href,
        licenseInfo.licenseKey,
      );

      // Open billing portal in new tab
      window.open(response.url, "_blank");
    } catch (error: unknown) {
      console.error("Failed to open billing portal:", error);

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Hide the Manage Billing control entirely when licenseType is missing or 'NORMAL'.
  2. Show an 'Upgrade' CTA instead of the Manage Billing button for free-tier users.
  3. Ensure licenseInfo is loaded and refreshed before rendering the section.

Example fix

// before
if (!licenseInfo?.licenseType || licenseInfo.licenseType === "NORMAL") {
  throw new Error("No valid license found. ...");
}

// after — gate the UI
const canManageBilling =
  !!licenseInfo?.licenseType && licenseInfo.licenseType !== "NORMAL";
return canManageBilling ? <ManageBillingButton /> : <UpgradePrompt />;
Defensive patterns

Strategy: validation

Validate before calling

const isPaidLicense =
  !!licenseInfo?.licenseType &&
  licenseInfo.licenseType !== "NORMAL";
// Only render Manage Billing when isPaidLicense is true

Type guard

function isPaidLicenseType(type: unknown): boolean {
  return typeof type === "string" && type !== "NORMAL" && type.length > 0;
}

Prevention

When it happens

Trigger: User with no licenseType, a falsy licenseType, or licenseType === 'NORMAL' clicks the Manage Billing control in the admin plan section.

Common situations: A free/NORMAL user reaches the admin config and tries to manage billing. License info failed to load (undefined). User downgraded to free and the cached licenseType is stale.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/ff53ea9e8dd651f0. Report an issue: GitHub.