toeverything/AFFiNE · error · UnsupportedClientVersion
unsupported_client_version
unsupported_client_version
Error message
Unsupported client with version [${clientVersion}], required version is [${requiredVersion}]. What it means
Thrown by RealtimeGateway.assertVersion (packages/backend/server/src/core/realtime/gateway.ts:165) at connection time. The client-supplied version must survive normalizeRealtimeClientVersion, pass semver.valid, and satisfy MIN_REALTIME_CLIENT_VERSION (currently >=0.26.0); otherwise UnsupportedClientVersion rejects the connection before any realtime traffic flows.
Solutions
- Upgrade the client to >=0.26.0 and send its real semver in the connection's version param.
- Custom clients: pass a valid semver string (e.g. from package.json) with every connect.
- After upgrading the server, re-check MIN_REALTIME_CLIENT_VERSION and raise the client floor accordingly.
Example fix
// before
const ws = new WebSocket(`${rtUrl}/global/sync`); // no version param
// after
const ws = new WebSocket(`${rtUrl}/global/sync?version=${pkg.version}`); // pkg.version >= 0.26.0 Defensive patterns
Strategy: validation
Validate before calling
import semver from 'semver';
const MIN_REALTIME_CLIENT_VERSION = '0.26.0';
function clientSupported(v?: string) {
return !!v && semver.valid(v) !== null && semver.gte(v, MIN_REALTIME_CLIENT_VERSION);
}
if (!clientSupported(clientVersion)) {
throw new Error('client version unsupported, update required');
} Type guard
const isUnsupportedClientVersion = (e: unknown): e is UnsupportedClientVersion => e instanceof UnsupportedClientVersion;
Try / catch
client.on('connect_error', (e) => {
if ((e as { code?: string }).code === 'unsupported_client_version') {
return promptForUpdate();
}
throw e;
}); Prevention
- Always ship the app's package version as the realtime version param.
- Keep an e2e test that connects with exactly the minimum supported client version.
When it happens
Trigger: Opening the realtime WebSocket/SSE endpoint with a version param below 0.26.0, a non-semver string, or no version at all (reported as 'unset_or_invalid').
Common situations: Old desktop/web client after a server upgrade, a custom bot that never sends a version, or a dev client with a placeholder version string after the minimum was bumped.
Related errors
- authentication_required
- INVALID_DELEGATED_EDITOR_SESSION
- unsupported_client_version
- AUTHENTICATION_REQUIRED
- bad_request
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/ee99cfca97d7dc80.
Report an issue: GitHub.
Appendix: source
Thrown at packages/backend/server/src/core/realtime/gateway.ts:165
@OnEvent('realtime.topic.changed', { suppressError: true })
onRealtimeTopicChanged(payload: RealtimePublishPayload) {
try {
this.publisher.publishLocal(payload);
} catch (error) {
this.logger.error('Failed to publish realtime event', error);
}
}
private assertVersion(clientVersion?: string) {
const normalized = clientVersion
? normalizeRealtimeClientVersion(clientVersion)
: null;
if (
!normalized ||
!semver.valid(normalized) ||
!MIN_REALTIME_CLIENT_VERSION.test(normalized)
) {
throw new UnsupportedClientVersion({
clientVersion: clientVersion ?? 'unset_or_invalid',
requiredVersion: '>=0.26.0',
});
}
}
}
View on GitHub (pinned to b4c8548c09)