I’m trying to understand an intermittent Extension Warehouse licensing issue that affects some users who have purchased my extensions.
Every now and then I get messages from users saying that one of my extensions reports them as unlicensed, even though they say they purchased it and their Extension Warehouse / account state appears to show the extension as active. In these cases, the extension itself is installed correctly and the native runtime/DLL loads correctly, but the license validation result returned to the extension says the user is not licensed.
For context, my extension uses the SketchUp C API:
SUGetExtensionLicense(extension_id, &license)
where extension_id is the Extension Warehouse UUID for the extension.
I added extra diagnostics and now log:
- SUResult returned by SUGetExtensionLicense
- license.is_licensed
- license.state
- license.days_remaining
- license.error_description
- my own mapped status/result
In the failing cases, the important situation is roughly:
- The extension is installed correctly.
- The native runtime loads correctly.
- The user says the extension is purchased/active in Extension Warehouse.
- But the licensing API can still return a result that maps to NotLicensed.
I have also done some testing myself and I’m a bit confused by the caching/refresh behavior. For example, after logging out of SketchUp, I can sometimes still get a licensed result. I’m also not fully sure how Extension Warehouse test licenses behave, because test licenses I assign seem to keep returning as licensed, and I don’t know whether that is because they are cached locally, tied to the current signed-in account, or handled differently from production purchases/trials.
So I’m trying to understand the intended lifecycle and best practices before assuming this is a bug.
My current understanding from the C API docs is:
- SUGetExtensionLicense returning SU_ERROR_NONE only means the API call succeeded.
- SUExtensionLicense::is_licensed is the main allow/deny flag.
- SUExtensionLicense::state is additional status detail.
- SUExtensionLicense::days_remaining is informational/debug display only.
- SUExtensionLicense::error_description is for debugging only and should not be parsed for behavior.
In my extension, the license can be checked when the user interacts with the extension, for example when opening the UI or running a command/generation action. Is that the recommended pattern? Or is it also acceptable to also check during extension load/startup? (I do both)
The documentation for SketchUp 2025+ says SUGetExtensionLicense can automatically try to fetch a license from Extension Warehouse if the license is missing on the current device, but that automatic fetching is skipped during SketchUp startup for performance reasons. Does that mean extension-load/startup checks should be avoided, and license checks should only happen after explicit user interaction?
I would appreciate clarification on the technical side:
-
Should extensions always use SUExtensionLicense::is_licensed as the authoritative allow/deny value, and treat state/days_remaining as informational?
-
Is Extension Warehouse license data cached locally by SketchUp?
If yes, is that cache per SketchUp version, per operating system user profile, per Trimble account, or shared across installed SketchUp versions?
-
What is expected after logout/login or switching Trimble accounts?
If a user logs out, is it expected that the C API may still return a licensed result because of local/offline cache?
-
What is the recommended way for a user to force a license refresh?
Restart SketchUp, sign out/in, press “Update License” in Extension Manager, reinstall from Extension Warehouse, or something else?
-
How are Extension Warehouse test licenses handled?
Do test licenses have the same caching and refresh behavior as real purchases/trials?
-
In SketchUp 2025+, when SUGetExtensionLicense attempts to automatically fetch a missing license from Extension Warehouse, what are the exact conditions for that fetch?
Does it require the user to be signed in, online, and not during startup? Are there other conditions?
-
Are there known cases where Extension Manager / Extension Warehouse account state shows the extension as active, but SUGetExtensionLicense still returns NotLicensed until the user refreshes, reinstalls, or signs in again?
I would also appreciate confirmation on the enum and ABI expectations. The SDK header defines:
enum SUExtensionLicenseState {
SUExtensionLicenseState_Licensed,
SUExtensionLicenseState_Expired,
SUExtensionLicenseState_Trial,
SUExtensionLicenseState_TrialExpired,
SUExtensionLicenseState_NotLicensed
};
Since the values are not explicitly assigned, I assume the C/C++ numeric mapping is:
0 = Licensed
1 = Expired
2 = Trial
3 = TrialExpired
4 = NotLicensed
Is that correct and stable across supported SketchUp versions?
Also, is the expected struct layout exactly:
bool is_licensed;
SUExtensionLicenseState state;
size_t days_remaining;
char error_description[512];
I’m asking because I’m calling the C API from a native runtime loaded by a Ruby extension, so I want to make sure I’m not accidentally relying on an ABI assumption that could differ between SDK/runtime versions or compilers.
I want my extensions to follow the intended API behavior and give users the right troubleshooting steps when Extension Warehouse/account state and the local API result appear to disagree.
If anyone from Trimble or anyone with deeper Extension Warehouse licensing experience can clarify this, I’d really appreciate it.