jlcodes99/cockpit-tools · warning
[Codex SSH] disable sync failed:
Error message
[Codex SSH] disable sync failed:
What it means
`handleToggle` disables Codex SSH sync by calling `selectServer(null)`, telling the backend to stop pushing settings to any SSH host. If that backend call rejects, the failure is logged but the switch state may already reflect 'off', silently diverging from the backend.
Source
Thrown at src/components/codex/CodexSshSyncSettingsControl.tsx:55
const enabled = Boolean(
selectedServer && selectedServer.sync_on_codex_switch,
);
const openModal = useCallback(() => setModalOpen(true), []);
const closeModal = useCallback(() => setModalOpen(false), []);
const handleToggle = async (next: boolean) => {
if (busy) return;
if (next) {
setModalOpen(true);
return;
}
setBusy(true);
try {
// 关闭:取消选中,后端切号同步不会再推到任何 SSH 主机
await selectServer(null);
} catch (error) {
console.warn('[Codex SSH] disable sync failed:', error);
} finally {
setBusy(false);
}
};
const hintText = enabled && selectedServer
? t('codex.ssh.syncSwitchActive', '已启用 · {{name}}({{user}}@{{host}})', {
name: selectedServer.name,
user: selectedServer.username,
host: selectedServer.host,
})
: t(
'codex.ssh.syncSwitchDesc',
'开启后配置 SSH 主机;Codex 切号时把当前账号同步到远端。',
);
if (variant === 'quick') {
return (View on GitHub (pinned to 1ed8b77992)
Solutions
- Check the logged error for the backend rejection cause and fix filesystem permissions on the SSH config it writes.
- Revert the toggle UI state to match the backend when the call fails, instead of leaving it optimistic.
- Retry `selectServer(null)` after the user fixes permissions, then confirm via re-reading current server selection.
- Ensure no concurrent sync operation is running when toggling.
Example fix
// before
} catch (error) {
console.warn('[Codex SSH] disable sync failed:', error);
}
// after
} catch (error) {
console.warn('[Codex SSH] disable sync failed:', error);
setEnabled(true); // roll back optimistic UI state
} Defensive patterns
Strategy: fallback
Validate before calling
const current = await getCurrentSelectedServer(); if (current === null) return; // already disabled; skip the call
Type guard
function isSelectedServer(v: unknown): v is string | null {
return v === null || typeof v === 'string';
} Try / catch
try {
await selectServer(null);
setEnabled(false);
} catch (error) {
console.warn('[Codex SSH] disable sync failed:', error);
setEnabled(true); // roll back optimistic state to match backend
} Prevention
- Roll back optimistic toggle state when the backend call fails
- Check SSH config file writability before toggling
- Re-read backend selection state after each toggle to confirm sync
- Avoid concurrent toggle/sync operations
When it happens
Trigger: The `selectServer(null)` backend call rejects: SSH config write fails (permissions on known_hosts/ssh config), the backend command errors, or the IPC channel is closed.
Common situations: Read-only SSH config file or missing write permissions; partially removed SSH host entries; backend upgrade changing the sync API; calling toggle while a previous sync is in progress.
Related errors
- [AccountGroups] Failed to load groups: ${String(error)}
- Claude login start 响应缺少关键字段
- 刷新 Codex 配额失败
- [AntigravityRuntime] failed to resolve preferred target:
- [WorkbuddyAutoCheckin] 从 Rust 端获取配置失败,使用本地缓存或默认值:
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/846185ddd85d685a.
Report an issue: GitHub.