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

  1. Check the logged error for the backend rejection cause and fix filesystem permissions on the SSH config it writes.
  2. Revert the toggle UI state to match the backend when the call fails, instead of leaving it optimistic.
  3. Retry `selectServer(null)` after the user fixes permissions, then confirm via re-reading current server selection.
  4. 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

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


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/846185ddd85d685a. Report an issue: GitHub.