Stirling-Tools/Stirling-PDF · warning · Error
No license key found. Please activate a license first.
Error message
No license key found. Please activate a license first.
What it means
Thrown by ManageBillingButton when licenseService.getLicenseInfo() returns an object whose licenseKey is falsy. The button assumes a license key exists to authenticate the billing-portal session creation; without one, the portal session cannot be created.
Source
Thrown at frontend/editor/src/proprietary/components/shared/ManageBillingButton.tsx:25
interface ManageBillingButtonProps {
returnUrl?: string;
}
export const ManageBillingButton: React.FC<ManageBillingButtonProps> = ({
returnUrl = window.location.href,
}) => {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const handleClick = async () => {
try {
setLoading(true);
// Get current license key for authentication
const licenseInfo = await licenseService.getLicenseInfo();
if (!licenseInfo.licenseKey) {
throw new Error(
"No license key found. Please activate a license first.",
);
}
// Create billing portal session with license key
const response = await licenseService.createBillingPortalSession(
returnUrl,
licenseInfo.licenseKey,
);
// Open billing portal in new tab
window.open(response.url, "_blank");
setLoading(false);
} catch (error: unknown) {
console.error("Failed to open billing portal:", error);
alert({
alertType: "error",
title: t("billing.portal.error", "Failed to open billing portal"),View on GitHub (pinned to 9ef20dcab8)
Solutions
- Hide or disable the Manage Billing button when no license key is present (check license info on mount).
- Redirect the user to the license activation flow before showing the billing button.
- On error, guide the user to activate a license first with a link/button to the activation page.
Example fix
// before
const licenseInfo = await licenseService.getLicenseInfo();
if (!licenseInfo.licenseKey) {
throw new Error("No license key found. Please activate a license first.");
}
// after — disable the button reactively and show activation prompt
const { licenseKey } = useLicenseInfo(); // hook reading license store
return (
<Button disabled={!licenseKey} onClick={handleClick}>
{licenseKey ? t("billing.manageBilling") : t("billing.activateLicense")}
</Button>
); Defensive patterns
Strategy: validation
Validate before calling
// Load license info reactively and disable the button when no key
const { licenseInfo } = useLicense();
const hasKey = !!licenseInfo?.licenseKey;
<Button disabled={!hasKey} ...> Type guard
function hasLicenseKey(info: unknown): boolean {
return !!info && typeof info === "object" && !!(info as { licenseKey?: unknown }).licenseKey;
} Prevention
- Gate the billing button on license presence before the click handler runs.
- Redirect unlicensed users to the activation flow.
- Refresh license info on mount to avoid stale empty state.
When it happens
Trigger: User clicks Manage Billing before activating any license. The license store is empty/cleared (fresh install, logged out, local storage wiped). getLicenseInfo() resolved but licenseKey was null/empty string.
Common situations: Self-hosted/desktop user without an activated license. License data was cleared from storage. A free-tier user with no purchase attempting to reach the billing portal.
Related errors
- No valid license found. Please purchase a license before acc
- License key missing. Please contact support.
- No team resolved yet
- Unknown policy category: ${id}
- Supabase is not configured. Please use static plans instead.
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/81382200e2642fc2.
Report an issue: GitHub.