{"record":{"id":"ee99cfca97d7dc80","repo":"toeverything/AFFiNE","slug":"unsupported-client-version-ee99cf","errorCode":"unsupported_client_version","errorMessage":"Unsupported client with version [${clientVersion}], required version is [${requiredVersion}].","messagePattern":"Unsupported client with version \\[(.+?)\\], required version is \\[(.+?)\\]\\.","errorType":"exception","errorClass":"UnsupportedClientVersion","httpStatus":403,"severity":"error","filePath":"packages/backend/server/src/core/realtime/gateway.ts","lineNumber":165,"sourceCode":"  @OnEvent('realtime.topic.changed', { suppressError: true })\n  onRealtimeTopicChanged(payload: RealtimePublishPayload) {\n    try {\n      this.publisher.publishLocal(payload);\n    } catch (error) {\n      this.logger.error('Failed to publish realtime event', error);\n    }\n  }\n\n  private assertVersion(clientVersion?: string) {\n    const normalized = clientVersion\n      ? normalizeRealtimeClientVersion(clientVersion)\n      : null;\n    if (\n      !normalized ||\n      !semver.valid(normalized) ||\n      !MIN_REALTIME_CLIENT_VERSION.test(normalized)\n    ) {\n      throw new UnsupportedClientVersion({\n        clientVersion: clientVersion ?? 'unset_or_invalid',\n        requiredVersion: '>=0.26.0',\n      });\n    }\n  }\n}\n","sourceCodeStart":147,"sourceCodeEnd":172,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/26c515e050211269e911f7d9cfe162a26c83ed98/packages/backend/server/src/core/realtime/gateway.ts#L147-L172","documentation":"Thrown by RealtimeGateway.assertVersion when the clientVersion on a realtime envelope is missing, unparseable, fails semver.valid, or does not satisfy MIN_REALTIME_CLIENT_VERSION (>=0.26.0-0, prereleases included). It blocks all realtime:request/subscribe/unsubscribe traffic from incompatible clients to prevent protocol drift.","triggerScenarios":"Client connects with clientVersion undefined/empty; canary build not in an allowed canary namespace; client version below 0.26.0; non-semver string passed as clientVersion.","commonSituations":"Old desktop/electron client pointing at a newer server; embedded webview shipping a stale blocksuite bundle; CI hitting the gateway with a raw socket and no version header; canary build deployed outside the canary namespace.","solutions":["Upgrade the client to >=0.26.0 and ensure the realtime envelope includes a valid semver clientVersion.","For canary builds, set env.namespaces.canary and use the canary-date version format.","If you control the client, send the same version reported to the version guard on /api/version.","As a last resort on a self-host dev box, downgrade the server or pin a compatible client."],"exampleFix":"// before\nsocket.emit('realtime:subscribe', { topic, input });\n\n// after\nsocket.emit('realtime:subscribe', {\n  clientVersion: APP_VERSION, // e.g. '0.26.0'\n  topic,\n  input,\n});","handlingStrategy":"validation","validationCode":"import semver from 'semver';\nconst MIN = new semver.Range('>=0.26.0-0', { includePrerelease: true });\nfunction clientOk(v?: string) {\n  return !!v && semver.valid(v) != null && MIN.test(v);\n}\nif (!clientOk(APP_VERSION)) {\n  // block realtime connect; show upgrade required banner\n}","typeGuard":"function isSemver(v: string): v is string {\n  return typeof v === 'string' && semver.valid(v) !== null;\n}","tryCatchPattern":"try {\n  await socket.connect();\n} catch (e) {\n  if (e?.code === 'unsupported_client_version') {\n    // show 'please update' UI and stop retrying\n    return showUpgradeRequired(e.requiredVersion);\n  }\n  throw e;\n}","preventionTips":["Embed the client version constant at build time and send it on every realtime envelope.","For canary builds, ensure env.namespaces.canary is configured on the server.","Run a version-compatibility smoke test against the server's MIN_REALTIME_CLIENT_VERSION in CI."],"tags":["realtime","versioning","semver","websocket","nestjs"],"backgroundTag":null,"analyzedSha":"26c515e050211269e911f7d9cfe162a26c83ed98","analyzedAt":"2026-08-12T13:15:16.447Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}