{"record":{"id":"3a6e7bde37388df5","repo":"jlcodes99/cockpit-tools","slug":"floatingcard-errors-stopinstancebeforeswitch","errorCode":"floatingCard.errors.stopInstanceBeforeSwitch","errorMessage":"请先停止实例再切换账号","messagePattern":"请先停止实例再切换账号","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/pages/FloatingCardWindow.tsx","lineNumber":1274,"sourceCode":"  const handleSwitch = useCallback(async () => {\n    if (!viewedAccount || switchingAccountId || isCurrentViewed) return;\n    setSwitchingAccountId(viewedAccount.id);\n    setErrorText(null);\n    try {\n      if (instanceContext) {\n        const instanceStore = resolveInstanceStoreApi(selectedPlatform);\n        if (!instanceStore) {\n          throw new Error(t('common.shared.instances.unsupported.title', '暂不支持当前系统'));\n        }\n        const instances = await instanceStore.refreshInstances();\n        const targetInstance = findInstanceById(instances, instanceContext.instanceId);\n        const wasRunning = targetInstance?.running === true;\n        if (\n          selectedPlatform === 'grok' &&\n          instanceContext.instanceId !== DEFAULT_INSTANCE_ID &&\n          wasRunning\n        ) {\n          throw new Error(\n            t(\n              'floatingCard.errors.stopInstanceBeforeSwitch',\n              '请先停止实例再切换账号',\n            ),\n          );\n        }\n        await instanceStore.updateInstance({\n          instanceId: instanceContext.instanceId,\n          bindAccountId: viewedAccount.id,\n          followLocalAccount: instanceContext.instanceId === DEFAULT_INSTANCE_ID ? false : undefined,\n        });\n        if (wasRunning) {\n          await instanceStore.startInstance(instanceContext.instanceId);\n        }\n        const nextContext = {\n          ...instanceContext,\n          boundAccountId: viewedAccount.id,\n        };","sourceCodeStart":1256,"sourceCodeEnd":1292,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/pages/FloatingCardWindow.tsx#L1256-L1292","documentation":"For the Grok platform specifically, switching accounts is only allowed when the running instance is the default one. If the instance context points at a non-default Grok instance that is currently running, the switch is rejected with 'floatingCard.errors.stopInstanceBeforeSwitch' ('请先停止实例再切换账号' — stop the instance before switching accounts).","triggerScenarios":"Calling switch-account from FloatingCardWindow while selectedPlatform === 'grok', instanceContext.instanceId !== DEFAULT_INSTANCE_ID, and the target instance's running === true (as determined by findInstanceById on refreshed instances).","commonSituations":"User launches a secondary Grok instance, leaves it running, then tries to swap accounts from the floating card; automations attempting account switches without first stopping running instances.","solutions":["Stop the running Grok instance, then retry the account switch.","Switch back to the default instance before switching accounts.","Catch the error in the UI and prompt the user with a 'stop instance' action before proceeding.","Guard caller-side: refresh instances, check running state, and stop the instance programmatically first."],"exampleFix":"// before\nawait switchAccount(nextAccountId);\n// after\nconst instances = await getInstances();\nconst inst = findInstanceById(instances, instanceId);\nif (platform === 'grok' && instanceId !== DEFAULT_INSTANCE_ID && inst?.running) {\n  await stopInstance(instanceId);\n}\nawait switchAccount(nextAccountId);","handlingStrategy":"validation","validationCode":"const instances = await getInstances();\nconst target = findInstanceById(instances, instanceId);\nconst mustStop = platform === 'grok' &&\n  instanceId !== DEFAULT_INSTANCE_ID &&\n  target?.running === true;\nif (mustStop) await stopInstance(instanceId); // before switching","typeGuard":"const isRunningNonDefault = (ctx: InstanceContext, list: Instance[]) => {\n  const inst = findInstanceById(list, ctx.instanceId);\n  return ctx.instanceId !== DEFAULT_INSTANCE_ID && inst?.running === true;\n};","tryCatchPattern":"try {\n  await switchAccount(nextAccountId);\n} catch (e) {\n  if (e.message.includes('stopInstanceBeforeSwitch')) {\n    await promptStopInstance(instanceId);\n    return;\n  }\n  throw e;\n}","preventionTips":["Refresh instance state immediately before switching so running status is fresh.","Offer a one-click 'stop and switch' flow for running non-default Grok instances.","Disable the switch action (with tooltip) while a non-default instance is running."],"tags":["instance-state","grok","precondition"],"backgroundTag":"instance-still-running","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}