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 insrc/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 insrc/kimi_cli/utils/proxy.py#L20-L32. The helper automatically rewritessocks://tosocks5://becausehttpxdoes not support the former, preventingAPIConnectionError. - 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:
- Check the UI message: The terminal already indicates whether the failure is a network, timeout, authentication, or server-side error.
- 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. - Validate environment: Run
echo $KIMI_API_KEY(or the provider-specific key) andenv | grep -i proxyto verify variables are set. - Force a token refresh: Execute
/loginin the interactive shell to re-authenticate any OAuth session. - Run a minimal request: Test with
kimi ask "Hello"; if it fails, usecurlagainst the provider endpoint to rule out system-wide networking issues. - Enable debug mode: Set
KIMI_LOG_LEVEL=DEBUG(via environment or.env) to capture verbose output fromloguru.
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-cliconverts low-level HTTP failures into structuredChatProviderErrorsubclasses (APIConnectionError,APITimeoutError,APIEmptyResponseError) defined in the kosong abstraction layer.- Automatic retry logic in
KimiSoulhandles transient errors and attempts OAuth token refresh for 401 responses before giving up. - Proxy auto-correction prevents common
socks://misconfigurations that crashhttpxconnections. - Diagnostic clarity comes from checking UI color codes, inspecting logs for the full stack trace, and validating
KIMI_API_KEYand proxy environment variables. - Re-authentication via
/loginresolves 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.
How do I fix proxy-related connection errors?
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →