-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Plugin Type
Kilo Code CLI
App Version
CLI version: 0.17.0
Description
GitHub Issue: kilocode CLI Race Condition
Repository: https://github.com/Kilo-Org/kilocode/issues/new
Title: CLI: Race condition corrupts config.json when multiple instances run in parallel
Bug Description
When running multiple kilocode CLI instances in parallel (e.g., via a wrapper script that spawns multiple agents), the config.json file can become corrupted with duplicate closing braces, resulting in invalid JSON.
Steps to Reproduce
- Run multiple kilocode CLI instances in parallel targeting the same config:
# Using a wrapper like ask-agent that spawns multiple kilocode instances
kilocode --model x-ai/grok-code-fast-1 "task" &
kilocode --model minimax/minimax-m2:free "task" &
kilocode --model mistralai/devstral-2512:free "task" &
wait- After several parallel runs,
~/.kilocode/cli/config.jsonmay become corrupted:
{
"version": "1.0.0",
...
"customThemes": {}
}
} // <-- Extra closing brace causes JSON parse errorExpected Behavior
Config file should remain valid JSON regardless of how many parallel instances run.
Actual Behavior
Config file becomes corrupted with duplicate closing braces, causing subsequent runs to fail with:
SyntaxError: Unexpected non-whitespace character after JSON at position 1430
Root Cause Analysis
In cli/src/config/persistence.ts:
loadConfig()(line ~169) always callssaveConfig()after loading to persist merged defaultssaveConfig()usesfs.writeFile()without any file locking- When multiple instances run in parallel, they race to write the config
- Simultaneous writes can result in partial/duplicate content
// persistence.ts line 169-173
// Save the merged config back to ensure all defaults are persisted
await saveConfig(config)
// persistence.ts saveConfig()
await fs.writeFile(configFile, JSON.stringify(config, null, 2)) // No locking!Suggested Fix
Add file locking around config read/write operations using a package like proper-lockfile:
import lockfile from 'proper-lockfile';
export async function saveConfig(config: CLIConfig): Promise<void> {
if (isEphemeralMode()) return;
await ensureConfigDir();
// Acquire lock before writing
const release = await lockfile.lock(configFile, { retries: 3 });
try {
await fs.writeFile(configFile, JSON.stringify(config, null, 2));
} finally {
await release();
}
}Alternatively, consider:
- Not writing config on every load (only when explicitly changed)
- Using atomic writes (write to temp file, then rename)
- Per-session config isolation for parallel mode
Environment
- OS: Windows 11
- kilocode CLI version: 0.17.0
- Node.js: v22.19.0
Workaround
Current workaround is to:
- Git-track the config file
- Run repair script after parallel operations:
# repair_config.py
import json, subprocess
from pathlib import Path
config = Path.home() / ".kilocode/cli/config.json"
try:
json.loads(config.read_text())
except json.JSONDecodeError:
subprocess.run(["git", "checkout", "config.json"], cwd=config.parent)Labels: bug, cli
Reproduction steps
Steps to Reproduce
- Run multiple kilocode CLI instances in parallel targeting the same config:
# Using a wrapper like ask-agent that spawns multiple kilocode instances
kilocode --model x-ai/grok-code-fast-1 "task" &
kilocode --model minimax/minimax-m2:free "task" &
kilocode --model mistralai/devstral-2512:free "task" &
wait- After several parallel runs,
~/.kilocode/cli/config.jsonmay become corrupted:
{
"version": "1.0.0",
...
"customThemes": {}
}
} // <-- Extra closing brace causes JSON parse errorProvider
Multiple free providers
Model
x-ai/grok-code-fast-1, minimax/minimax-m2:free, mistralai/devstral-2512:free
System Information
OS: Windows 11
kilocode CLI version: 0.17.0
Node.js: v22.19.0
Metadata
Metadata
Assignees
Labels
Type
Projects
Status