How to Troubleshoot Connection Errors with kimi-cli: Complete Diagnostics Guide

Connection errors in kimi-cli surface as APIConnectionError, APITimeoutError, or APIEmptyResponseError from the kosong provider layer, which the KimiSoul core loop classifies, retries automatically, and surfaces to the UI with specific remediation steps such as running /login for authentication failures.

The kimi-cli tool by MoonshotAI communicates with LLM providers through the kosong chat-provider abstraction. When HTTP connectivity fails, the runtime transforms raw socket errors into structured ChatProviderError subclasses, enabling automated recovery flows and actionable user feedback to help you troubleshoot connection errors with kimi-cli efficiently.

Understanding Connection Error Types

The kosong abstraction defines three primary exceptions that indicate network-level failures. In packages/kosong/src/kosong/chat_provider/__init__.py#L46-L50, the provider raises:

  • APIConnectionError: Indicates the HTTP client cannot establish a TCP connection due to socket errors, DNS resolution failures, or proxy misconfigurations.
  • APITimeoutError: Raised when a request exceeds the configured timeout duration.
  • APIEmptyResponseError: Signifies a successful TCP connection that returned an empty payload.

These exceptions inherit from ChatProviderError and propagate through the KimiSoul event loop for classification and handling.

Error Classification and Telemetry

Before displaying an error, KimiSoul maps raw exceptions to shorthand types for telemetry and UI color-coding. The classify_api_error function in src/kimi_cli/soul/kimisoul.py#L14-L53 implements this logic:

def classify_api_error(e: Exception) -> tuple[str, int | None]:
    …
    if isinstance(e, APIConnectionError):
        return "network", None
    if isinstance(e, (APITimeoutError, TimeoutError)):
        return "timeout", None
    …

This classification feeds the _track_api_error telemetry helper (lines L91‑L99) and determines the color and message shown in the terminal interface.

Automatic Retry and Recovery Logic

KimiSoul wraps every LLM invocation in a tenacity retry loop that consults _is_retryable_error to determine whether to attempt recovery. As implemented in src/kimi_cli/soul/kimisoul.py#L46-L58:

def _is_retryable_error(exception: BaseException) -> bool:
    if isinstance(exception, (APIConnectionError, APITimeoutError)):
        return not bool(getattr(exception, "_kimi_recovery_exhausted", False))
    …
    return isinstance(exception, APIStatusError) and exception.status_code in (
        429, 500, 502, 503, 504,
    )

For transient failures, _run_with_connection_recovery (lines L60‑L100) attempts an OAuth token refresh when the provider supports it, then re-executes the original operation:

async def _run_with_connection_recovery(...):
    try:
        return await operation()
    except APIStatusError as error:
        if error.status_code != 401 or _auth_retried:
            raise
        …
        await self._runtime.oauth.ensure_fresh(self._runtime, force=True)
        return await self._run_with_connection_recovery(..., _auth_retried=True)

If the provider uses API-key authentication only, the retry logic skips the refresh step and proceeds with exponential backoff.

Configuration Issues That Trigger Connection Errors

Several environment and configuration variables directly impact connectivity:

  • API Keys (KIMI_API_KEY, OPENAI_API_KEY, …): Loaded in src/kimi_cli/llm.py‑L311). Missing or incorrect keys result in 401 errors that the UI reports as "Authorization failed".
  • Proxy Environment (ALL_PROXY, HTTP_PROXY, …): Normalized in src/kimi_cli/utils/proxy.py#L20-L32. The helper automatically rewrites socks:// to socks5:// because httpx does not support the former, preventing APIConnectionError.
  • OAuth Token Expiry: Handled in src/kimi_cli/soul/kimisoul.py#L72‑L90. When an OAuth provider returns 401, the system attempts automatic token refresh before surfacing the error.
  • HTTP Header Whitespace: A known Linux kernel bug can introduce trailing newlines in headers; the codebase strips these before sending to prevent server rejection.

Step-by-Step Diagnostic Workflow

Follow this sequence to isolate and resolve connectivity issues:

  1. Check the UI message: The terminal already indicates whether the failure is a network, timeout, authentication, or server-side error.
  2. Inspect the log: Search for the logger.exception("LLM provider error:") line in the shell or print UI output; the stack trace reveals the original exception class.
  3. Validate environment: Run echo $KIMI_API_KEY (or the provider-specific key) and env | grep -i proxy to verify variables are set.
  4. Force a token refresh: Execute /login in the interactive shell to re-authenticate any OAuth session.
  5. Run a minimal request: Test with kimi ask "Hello"; if it fails, use curl against the provider endpoint to rule out system-wide networking issues.
  6. Enable debug mode: Set KIMI_LOG_LEVEL=DEBUG (via environment or .env) to capture verbose output from loguru.

Code Examples for Debugging Connection Issues

Reproduce a Connection Error with a Mock Provider

Use this pattern to test how the UI handles network failures:

from kosong.chat_provider import APIConnectionError
from kimi_cli.soul.kimisoul import KimiSoul

class BrokenProvider:
    async def chat(self, *_, **__):
        raise APIConnectionError("simulated network failure")

# Inject the broken provider into a fresh runtime (simplified)

runtime = ...   # obtain a Runtime instance via KimiCLI.create()

runtime.llm = BrokenProvider()
soul = KimiSoul(runtime)

# This triggers the retry loop and surfaces the error to the UI

await soul.run_once()

Verify Environment Variables

Run this script to audit your configuration:

import os
for var in ("KIMI_API_KEY", "OPENAI_API_KEY", "ALL_PROXY", "HTTP_PROXY"):
    print(f"{var} = {os.getenv(var)!r}")

Trigger Manual Token Refresh

In the interactive shell, execute:

/login

The CLI initiates the provider-specific login flow, refreshing OAuth tokens or updating API keys as needed.

Summary

  • kimi-cli converts low-level HTTP failures into structured ChatProviderError subclasses (APIConnectionError, APITimeoutError, APIEmptyResponseError) defined in the kosong abstraction layer.
  • Automatic retry logic in KimiSoul handles transient errors and attempts OAuth token refresh for 401 responses before giving up.
  • Proxy auto-correction prevents common socks:// misconfigurations that crash httpx connections.
  • Diagnostic clarity comes from checking UI color codes, inspecting logs for the full stack trace, and validating KIMI_API_KEY and proxy environment variables.
  • Re-authentication via /login resolves most authorization-related connection failures.

Frequently Asked Questions

What does APIConnectionError mean in kimi-cli?

APIConnectionError indicates the HTTP client could not establish a TCP connection to the LLM provider, typically caused by DNS resolution failures, socket timeouts, or proxy misconfigurations in src/kimi_cli/utils/proxy.py. Check your network connectivity and proxy settings, then verify the endpoint is reachable with a tool like curl.

Ensure your ALL_PROXY or HTTP_PROXY variables use socks5:// instead of socks://, as the underlying httpx library does not support the latter scheme. The proxy normalization logic in src/kimi_cli/utils/proxy.py#L20-L32 attempts to auto-correct this, but explicit socks5:// formatting prevents initialization errors.

Why does kimi-cli retry failed requests multiple times?

The KimiSoul core loop implements a tenacity-based retry mechanism that treats APIConnectionError, APITimeoutError, and specific HTTP status codes (429, 500, 502, 503, 504) as transient. It attempts recovery—including OAuth token refresh for 401 errors—before surfacing a final error to the user interface.

How do I re-authenticate when I see an authorization failure?

When the UI displays "Authorization failed" (usually accompanied by a 401 status code), type /login in the interactive shell. This forces a fresh OAuth token refresh or API key re-entry, which the _run_with_connection_recovery method in src/kimi_cli/soul/kimisoul.py executes automatically during the next request attempt.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →