{"record":{"id":"d00a061c5eaae2be","repo":"hcengineering/platform","slug":"model-version-mismatch","errorCode":null,"errorMessage":"Model version mismatch","messagePattern":"Model version mismatch","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"foundations/server/packages/server/src/sessionManager.ts","lineNumber":617,"sourceCode":"\n    if (isWorkspaceCreating(workspaceInfo.mode)) {\n      // No access to workspace for token.\n      return { resp: { error: new Error(`Workspace during creation phase...${workspaceUuid}`) } }\n    }\n\n    const wsVersion: Data<Version> = {\n      major: workspaceInfo.version.versionMajor,\n      minor: workspaceInfo.version.versionMinor,\n      patch: workspaceInfo.version.versionPatch\n    }\n\n    if (\n      this.modelVersion !== '' &&\n      this.modelVersion !== versionToString(wsVersion) &&\n      token.extra?.model !== 'upgrade' &&\n      token.extra?.mode !== 'backup'\n    ) {\n      ctx.warn('Model version mismatch', {\n        source: token.extra?.service ?? 'user',\n        version: this.modelVersion,\n        workspaceVersion: versionToString(wsVersion),\n        workspace: workspaceUuid\n      })\n      // Version mismatch, return upgrading.\n      return {\n        resp: { upgrade: true, progress: workspaceInfo.mode === 'upgrading' ? (workspaceInfo.progress ?? 0) : 0 }\n      }\n    }\n\n    let workspace = this.workspaces.get(workspaceUuid)\n    if (workspace?.closing !== undefined) {\n      await workspace?.closing\n    }\n\n    workspace = this.workspaces.get(workspaceUuid)\n","sourceCodeStart":599,"sourceCodeEnd":635,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/server/src/sessionManager.ts#L599-L635","documentation":"Warning emitted by TSessionManager.getWorkspace when a client's token asks to connect to a workspace whose data model version differs from the server's running modelVersion, and the connection is neither an 'upgrade' model connection nor a 'backup' mode connection. The server refuses the connection and responds with { upgrade: true } so the client reconnects and runs the model upgrade flow first.","triggerScenarios":"getWorkspace is called and: this.modelVersion !== '' AND this.modelVersion !== versionToString(wsVersion) (computed from workspaceInfo.version.versionMajor/Minor/Patch) AND token.extra?.model !== 'upgrade' AND token.extra?.mode !== 'backup'. The workspaceInfo comes from the workspace service; the mismatch means the workspace DB has not been migrated to the server's version yet.","commonSituations":"Server deployed with a new model version while the workspace still points at the old version; client tools bypassing the upgrade endpoint and connecting with a normal user token mid-rollout; stale workspaceInfo cache after a failed upgrade; backup-mode exclusions not applied because token.extra.mode is unset.","solutions":["Let the client follow the 'upgrade' response: reconnect with token.extra.model='upgrade' so switchToUpgradeSession / the upgrade pipeline migrates the workspace model.","Verify the workspace's registered version in the workspace service matches the server's modelVersion; trigger an upgrade job for lagging workspaces.","If this is an intentional backup/restore operation, ensure the token carries extra.mode='backup' so the mismatch check is skipped.","Check that workspaceInfo.version returned by the workspace service is not stale (clear workspaceInfoCache or force a refresh)."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const wsInfo = await workspaceService.getWorkspaceInfo(wsUuid)\nconst wsVersion = `${wsInfo.version.versionMajor}.${wsInfo.version.versionMinor}.${wsInfo.version.versionPatch}`\nif (wsVersion !== serverModelVersion && token.extra?.model !== 'upgrade') {\n  await triggerWorkspaceUpgrade(wsUuid)\n}","typeGuard":"function canConnect(modelVersion: string, wsVersion: string, token: Token): boolean {\n  return modelVersion === '' || modelVersion === wsVersion || token.extra?.model === 'upgrade' || token.extra?.mode === 'backup'\n}","tryCatchPattern":"const { resp, workspace } = await sessionManager.getWorkspace(ctx, wsUuid, info, token, socket)\nif (resp?.upgrade) {\n  await reconnectWithUpgradeToken(wsUuid) // retry with token.extra.model = 'upgrade'\n}","preventionTips":["Run upgrades through the official upgrade flow instead of connecting user tokens to mismatched workspaces.","Keep workspace version registry in sync with deploys; upgrade lagging workspaces as part of rollout.","Gate deploys on a version-skew check across workspaces.","Pass extra.mode='backup' on backup/restore connections."],"tags":["versioning","upgrade","migrations","workspace"],"backgroundTag":"model-version-mismatch","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}