jlcodes99/cockpit-tools · error
floatingCard.errors.stopInstanceBeforeSwitch
floatingCard.errors.stopInstanceBeforeSwitch
Error message
请先停止实例再切换账号
What it means
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).
Source
Thrown at src/pages/FloatingCardWindow.tsx:1274
const handleSwitch = useCallback(async () => {
if (!viewedAccount || switchingAccountId || isCurrentViewed) return;
setSwitchingAccountId(viewedAccount.id);
setErrorText(null);
try {
if (instanceContext) {
const instanceStore = resolveInstanceStoreApi(selectedPlatform);
if (!instanceStore) {
throw new Error(t('common.shared.instances.unsupported.title', '暂不支持当前系统'));
}
const instances = await instanceStore.refreshInstances();
const targetInstance = findInstanceById(instances, instanceContext.instanceId);
const wasRunning = targetInstance?.running === true;
if (
selectedPlatform === 'grok' &&
instanceContext.instanceId !== DEFAULT_INSTANCE_ID &&
wasRunning
) {
throw new Error(
t(
'floatingCard.errors.stopInstanceBeforeSwitch',
'请先停止实例再切换账号',
),
);
}
await instanceStore.updateInstance({
instanceId: instanceContext.instanceId,
bindAccountId: viewedAccount.id,
followLocalAccount: instanceContext.instanceId === DEFAULT_INSTANCE_ID ? false : undefined,
});
if (wasRunning) {
await instanceStore.startInstance(instanceContext.instanceId);
}
const nextContext = {
...instanceContext,
boundAccountId: viewedAccount.id,
};View on GitHub (pinned to 1ed8b77992)
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.
Example fix
// before
await switchAccount(nextAccountId);
// after
const instances = await getInstances();
const inst = findInstanceById(instances, instanceId);
if (platform === 'grok' && instanceId !== DEFAULT_INSTANCE_ID && inst?.running) {
await stopInstance(instanceId);
}
await switchAccount(nextAccountId); Defensive patterns
Strategy: validation
Validate before calling
const instances = await getInstances(); const target = findInstanceById(instances, instanceId); const mustStop = platform === 'grok' && instanceId !== DEFAULT_INSTANCE_ID && target?.running === true; if (mustStop) await stopInstance(instanceId); // before switching
Type guard
const isRunningNonDefault = (ctx: InstanceContext, list: Instance[]) => {
const inst = findInstanceById(list, ctx.instanceId);
return ctx.instanceId !== DEFAULT_INSTANCE_ID && inst?.running === true;
}; Try / catch
try {
await switchAccount(nextAccountId);
} catch (e) {
if (e.message.includes('stopInstanceBeforeSwitch')) {
await promptStopInstance(instanceId);
return;
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/3a6e7bde37388df5.
Report an issue: GitHub.