toeverything/AFFiNE · error · InternalServerError
internal_server_error
internal_server_error
Error message
An internal error occurred.
What it means
remoteLicense() normalizes the response from the AFFiNE Pro license cloud API (activate/deactivate). After throwRemoteLicenseError confirms error is absent, an intact response must contain response.license; if it does not, the response is malformed and InternalServerError('Invalid AFFiNE Pro license response.') is thrown. This signals an unexpected protocol violation from the license service rather than a client mistake.
Source
Thrown at packages/backend/server/src/plugins/license/service.ts:463
e instanceof UserFriendlyError &&
e.name !== 'internal_server_error'
) {
this.event.emit('workspace.subscription.canceled', {
workspaceId: license.workspaceId,
plan: SubscriptionPlan.SelfHostedTeam,
recurring: SubscriptionRecurring.Monthly,
});
await this.entitlement.revokeBySubject('selfhost_license', license.key);
}
return null;
}
}
private remoteLicense(response: LicenseResponse) {
this.throwRemoteLicenseError(response.error);
if (!response.license) {
throw new InternalServerError('Invalid AFFiNE Pro license response.');
}
return response.license;
}
private remoteCommand(response: CommandResponse) {
this.throwRemoteLicenseError(response.error);
}
private remotePortal(response: PortalResponse) {
this.throwRemoteLicenseError(response.error);
if (!response.url) {
throw new InternalServerError('Invalid AFFiNE Pro portal response.');
}
return { url: response.url };
}
private throwRemoteLicenseError(
error?: LicenseError | nullView on GitHub (pinned to b4c8548c09)
Solutions
- Retry once after a short delay — malformed 2xx bodies are usually transient.
- Inspect egress: disable any corporate proxy/SSL-inspection rewriting for https://app.affine.pro, or fix the reverse-proxy body-filter rules.
- Capture the raw response (log licenseClient traffic in dev) and check the AFFiNE Pro status page / support if the shape changed — a persistent failure indicates an upstream contract change requiring a server update.
Defensive patterns
Strategy: retry
Type guard
function isInternalServerError(e: unknown): e is InternalServerError {
return e instanceof InternalServerError;
} Try / catch
async function withLicenseRetry<T>(fn: () => Promise<T>, attempts = 2): Promise<T> {
for (let i = 0; ; i++) {
try {
return await fn();
} catch (e) {
if (i >= attempts || !(e instanceof InternalServerError)) throw e;
await new Promise(r => setTimeout(r, 500 * 2 ** i));
}
}
} Prevention
- Keep the HTTPS path to app.affine.pro free of body-rewriting proxies.
- Monitor upstream license API availability from the server host.
- Log the raw response body in dev when a malformed-response 500 appears.
When it happens
Trigger: licenseClient.activate({ licenseKey }) or deactivate returning HTTP 2xx with an empty or schema-breaking body — e.g. a proxy (nginx/Cloudflare) intercepting and rewriting the response, an API version change on app.affine.pro, or a truncated response.
Common situations: Self-hosted deployments behind corporate proxies that strip or replace response bodies; transient CDN corruption; upstream deploying a breaking API change; responses buffered/served from cache incorrectly.
Related errors
- failed_to_save_updates
- failed_to_upsert_snapshot
- bad_request
- license_expired
- invalid_license_to_activate
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/6a704968613740b3.
Report an issue: GitHub.