Why does an expired license still activate? How license expiration works in SOLO Server
Quick answer
A SOLO Server license does not expire on its own just because a date passed. It expires only when you have configured it to, in one of two ways, and enforced that configuration. If an expired license still activates or still runs, it is almost always because one of these two models is not fully set up, not because of clock tampering or a bug.
The two models are:
- Date-based expiration. The license carries an end date (Download Until, which becomes EffectiveEndDate in the Protection PLUS 5 SDK license file). Your application compares that date to the current date and stops running when it has passed. You enforce it in your code.
- Status-based expiration. The license Status field is set to Expired (for example, when a subscription is not renewed). On its next check-in with SOLO Server, the software deactivates. SOLO Server enforces it, as long as your software is required to validate periodically.
Pick one model per product. The rest of this article explains why an expired license still activates, and how to make each model actually enforce.
Why an expired license still activates
There are three separate facts that, together, explain almost every "it should be expired but it still works" report:
- Passing the expiration date does not change the license Status. The Download Until date passing does not automatically flip the Status to Expired. SOLO Server leaves the Status alone, so on its own, a passed date does nothing.
- Only one Product Option Type rejects an expired activation. The Option Type Activation Code with Days Left makes SOLO Server refuse an activation request when the license's Download Until date is in the past (it returns error 5019: License ID has expired). Every other Option Type will complete the activation even if the date has passed.
- Changing the Option Type does not remove the expiration date already on the license. If a license was created with a Download Until date and you later switch its Product Option to a different Type, the Download Until date (and therefore the EffectiveEndDate in the license file) stays populated. What changes is that SOLO Server no longer rejects the expired activation. The date is still there, so enforcement falls entirely to your application's own date check. If your code does not check EffectiveEndDate, the license runs with no expiration even though the date is present.
In short: unless you are using Activation Code with Days Left, SOLO Server will activate the license, and only your application deciding to honor EffectiveEndDate stops it from running.
Model 1: Date-based expiration (EffectiveEndDate)
Use this when the software should stop working on a specific date, such as a fixed-term or lease license.
How to configure it (SOLO Server):
- On the Product Option, set the Option Type to Activation Code with Days Left. This is the only Type that also rejects an expired activation server-side (error 5019), which gives customers a clear result instead of activating and then failing the local date check.
- Set Days to D/L (Days to Download) to the length of the term (for example, 365). When a license is created, SOLO Server adds this to the entered date and stores the result in the license's Download Until field.
- Optionally enable Reset Expiration at Activation so the term starts on first activation rather than on the order date.
How enforcement works: The Download Until date rides down into the Protection PLUS 5 SDK license file as the EffectiveEndDate property. Your application must compare EffectiveEndDate to the current date and treat the license as expired once the current date is past it. SOLO Server does not do this comparison for you at runtime; your code does. Non-expiring (perpetual) licenses simply should not have their EffectiveEndDate validated.
A note on trigger-code numbers: in Protection PLUS 5 SDK, the trigger-code number is just a convention your own code interprets, not a fixed rule. Several of the Protection PLUS 5 SDK samples use Trigger Code 11 for a time-limited (subscription/lease) license and Trigger Code 1 for a non-expiring license, but you can use any numbers you want as long as your application's logic matches what you configure in SOLO Server. (This differs from the older Instant Protection PLUS 3, where certain trigger-code numbers have fixed built-in meanings.)
For step-by-step setup, see Time-limited / subscription licenses with Protection PLUS 5 SDK and Subscription licenses with Protection PLUS 5 SDK. For the exact property to validate in code, see the Protection PLUS 5 SDK manual topics for validating time (PLUSManaged) and validating time (PLUSNative).
Model 2: Status-based expiration (License Status = Expired)
Use this when a subscription should stay valid only while the customer keeps paying, rather than expiring on a fixed date. This is the model used by recurring-billing integrations such as FastSpring.
How it works: When a subscription is not renewed, the License Status is set to Expired (for example, by a FastSpring event, or manually). A non-OK status deactivates the software the next time it validates or checks in with SOLO Server, and SOLO Server returns error 5017: Invalid License Status. No new activations are accepted, and the customer cannot download files.
Critical requirement: Status-based expiration only works if your software is required to validate with SOLO Server periodically. If validation is optional, a customer can avoid the expiration by simply blocking the connection to SOLO Server, and the Expired status is never seen.
With this model you typically use Option Type: Activation Code, Days to Download: 0 (no date), and rely on the Status field for enforcement. For the full recurring-billing setup, see Automatic recurring billing subscriptions and the FastSpring section of Subscription licenses with Protection PLUS 5 SDK. For what each status means, see License Status field in SOLO Server.
How the expiration fields connect
These fields are easy to confuse, so here is the plain-text relationship:
- Days to D/L (Days to Download): a Product Option setting. On license creation (or on first activation, if Reset Expiration at Activation is enabled), SOLO Server adds this number of days to the start date to compute the license's Download Until date. Set it to 0 for perpetual/no-expiration.
- Download Until: a date stored on the license. It controls download access in the Customer License Portal, and it can double as the license's expiration date. Passing this date does not change the license Status by itself.
- EffectiveEndDate: the date inside the Protection PLUS 5 SDK license file, populated from Download Until. This is the value your application validates against the current date to enforce a date-based expiration.
- Days Left: this is not a stored field. It is a number calculated at activation time (Download Until minus the current date) and sent as trigger-code Event Data when the Option Type is Activation Code with Days Left.
Common Questions
My license passed its expiration date, but it still activates and runs. Why?
Because a passed date does not expire a license on its own. Unless the Product Option Type is Activation Code with Days Left (which rejects the activation with error 5019), SOLO Server completes the activation, and only your application's own check of EffectiveEndDate stops the software from running. If your code does not validate EffectiveEndDate, the license runs indefinitely. This is not clock tampering and is not Trigger Code 48; it is a configuration/enforcement gap.
I changed the Product Option Type to stop expiration. Why is the license still expiring (or still carrying a date)?
Changing the Option Type does not remove the Download Until date that is already on an existing license, so that date still passes down as EffectiveEndDate in the license file. Switching away from Activation Code with Days Left only stops the server-side activation rejection (5019); it does not clear the date. To make a specific license non-expiring, clear or extend its Download Until date, and make sure your application does not validate EffectiveEndDate for that license.
What is the difference between errors 5019, 5017, and 5022?
They are three different expiration-related failures, and they mean different things:
- 5019 – License ID has expired: returned at activation when the Option Type is Activation Code with Days Left and the Download Until date is in the past.
- 5017 – Invalid License Status: returned when the license Status is not OK (for example, Expired). This is the status-based model.
- 5022 – system clock: returned when the device's clock is outside the allowed window for an offline or manual (trigger-code) activation request. On SOLO Server Shared URL (secure.softwarekey.com) that window is 24 hours; other hosted instances and self-hosted SOLO Server can be configured to a different value. This is a clock/date problem on the device, not a subscription-expiration problem, so the fix is to correct the clock and resubmit, not to reset the license.
Do I need to require periodic validation?
For status-based expiration, yes. If your software is not required to check in with SOLO Server on a schedule, a customer can block the connection and never receive the Expired status. For date-based expiration, the enforcement is local (your app checks EffectiveEndDate), so periodic validation is not required for the date check itself, though it is still good practice.
Is "license expired" the same as "software maintenance expired"?
No. Software maintenance expiration controls whether a customer can access newer versions of your software; the existing licensed version keeps working. License expiration controls whether the software runs at all. Both can use the Download Until date, so be clear about which one you intend. For the maintenance/version-gating pattern, see How do I restrict customers with expired software maintenance from accessing newer versions of my software?.