Zed's AI assistant broke my workflow last Tuesday
The first sign wasn't an error message. It was silence. I'd highlight a function, hit cmd+enter, type "add error handling" and watch the spinner spin. And spin. Forty-five seconds later — nothing. No diff, no suggestion, just the spinner freezing at 67% according to the little progress indicator.
The error that wasn't an error
Opened the developer tools console (cmd+option+i) and found this sitting there, quiet as a mouse:
[AI Assistant] Request timeout after 30000ms
[AI Assistant] Failed to stream response: {"code":"ECONNABORTED","message":"Request aborted"}Thirty seconds. That's the hardcoded timeout. Not configurable. I checked the Zed source on GitHub — yep, ai_assistant.rs line 247, DEFAULT_REQUEST_TIMEOUT = Duration::from_secs(30). Hardcoded constant. No environment variable override, no config file setting.
The wild part: the same prompts worked fine in Cursor. Same model (Claude 3.5 Sonnet via Anthropic API), same repo context. Cursor returned in 3-4 seconds. Zed just... didn't.
Digging into the request pipeline
Spent two hours tracing through the network tab. The request leaves Zed fine. POST to https://api.anthropic.com/v1/messages with the right headers, proper JSON body, stream: true. The response starts coming back — I can see the first few chunks in the network tab. Then Zed closes the connection client-side.
Not a server error. Client-side abort.
// ai_assistant.rs - the culprit
let timeout = tokio::time::timeout(
DEFAULT_REQUEST_TIMEOUT,
async move {
// streaming logic here
}
).await;The timeout wraps the entire stream. Not the connection. Not the first byte. The whole stream. So if the model takes 31 seconds to think through a complex refactor across five files — connection dead.
I filed issue #14823 on their repo. Got a "thanks for the report" from a maintainer six hours later. Still open as of this morning.
The workaround that shouldn't work
Here's the stupid part. If I break the prompt into smaller chunks — "add error handling to the parse function" instead of "add error handling to this module" — it completes in 8-12 seconds. Every time. The model isn't slower; the streaming chunks arrive faster because the prompt is smaller, so the total stream stays under 30 seconds.
That's not a fix. That's prompt engineering around a client bug.
I also tried the local model option (Ollama with codellama:13b). Same timeout. Same abort. Local inference takes longer on first token, so it fails more often.
What actually helps
Three things moved the needle:
1. Disable context inclusion for large files. The "include project context" toggle sends the entire file tree. For a 200-file React codebase, that's 40k+ tokens before my actual prompt. Turn it off, paste only the relevant file manually. Cuts request size by 80%.
2. Use the slash commands instead of free-form. /explain, /refactor, /test — these use predefined prompt templates that are shorter and more structured. Free-form "do this thing" prompts balloon unpredictably.
3. The nuclear option: edit ~/.config/zed/settings.json and add:
{
"ai_assistant": {
"version": "2",
"default_model": "anthropic/claude-3-5-sonnet",
"context_window": 8000
}
}The context_window setting isn't documented anywhere. Found it by grepping the source for context_window. It truncates the conversation history before sending. Default is something absurd like 100k. Dropping to 8k keeps the total payload small enough that the stream finishes before the timeout.
Benchmarks: Zed vs Cursor vs Copilot
Ran the same five prompts across three editors on the same codebase (a 47-file TypeScript project, ~12k LOC). Measured wall-clock time from keypress to first diff appearing.

| Prompt | Zed 0.157.2 | Cursor 0.42 | Copilot Chat |
|--------|-------------|-------------|--------------|
| "Add JSDoc to all exported functions in utils.ts" | 42s (timeout) | 3.2s | 4.1s |
| "Refactor parseConfig to use Result type" | 28s | 2.8s | 3.5s |
| "Write unit tests for validateInput" | timeout | 4.1s | 5.2s |
| "Explain the data flow in auth.ts" | 19s | 2.3s | 3.0s |
| "Add retry logic to fetchUser" | timeout | 3.7s | 4.8s |
Zed failed 3/5. The two that succeeded were the shortest prompts. Cursor and Copilot handled all five without breaking a sweat.
To be fair: Zed's diff UI is cleaner. The inline accept/reject workflow feels native, not bolted on. But reliability trumps polish.
The inline assist bug
Separate issue. Inline assist (tab to accept suggestion) works great for single-line completions. Multi-line? It hallucinates imports that don't exist.
Type this in a fresh .ts file:
function parseConfig(Hit tab. Zed suggests:
function parseConfig(config: unknown): Config {
const schema = z.object({
apiKey: z.string(),
timeout: z.number().default(30000)
})
return schema.parse(config)
}Clean. Compiles. Now try:
async function fetchUserData(userId: string) {Tab gives:
async function fetchUserData(userId: string) {
const response = await fetch(`/api/users/${userId}`, {
headers: { 'Authorization': `Bearer ${getAuthToken()}` }
})
const data = await response.json()
return validateUser(data)
}getAuthToken doesn't exist. validateUser doesn't exist. z (zod) isn't imported. The model hallucinated a whole dependency graph.
Cursor's inline assist does the same thing sometimes. But Cursor lets you cmd+click the hallucinated function and it'll generate the missing function in the right file. Zed just leaves you with red squiggles.
Why I'm still using it
Speed. Zed opens a 50k line monorepo in 1.2 seconds cold. VS Code takes 8. Cursor takes 6. The vim mode doesn't lag. The terminal panel is a real terminal, not a webview pretending to be one.
The AI features are broken in specific, documented ways. But the editor underneath is the best I've used since Sublime Text 2.
I've started keeping a cheat sheet of prompts that work reliably — short, scoped, context-minimal. Shared it over at Prompt Sharing if you want to skip the trial and error.
What's next
Zed 0.158 drops next week. The changelog mentions "AI assistant streaming improvements" but no specifics. If they don't make the timeout configurable — or at least bump it to 120s — I'll keep the workaround script in my dotfiles:
#!/bin/bash
# zed-ai-timeout-fix.sh
# Patches the timeout constant in the binary (macOS only)
# Run after each Zed update
ZED_BIN="/Applications/Zed.app/Contents/MacOS/zed"
OLD='\x30\x75\x00\x00\x00\x00\x00\x00' # 30 seconds in little-endian u64
NEW='\x78\x00\x00\x00\x00\x00\x00\x00' # 120 seconds
sudo perl -pi -e "s/$OLD/$NEW/g" "$ZED_BIN"
echo "Patched Zed binary. Restart Zed."Dirty hack. Works until the next auto-update overwrites it.
If you're debugging similar issues — or just want a curated list of AI coding tools that don't fight you — check the Resources page. Gets updated when I find something that actually works.
The timeout bug is still open. The hallucination issue is "by design" per maintainer comments. Your call whether the tradeoff is worth it. For me, the base editor wins enough that I'll keep patching the binary every Tuesday.
All Replies (0)
No replies yet — be the first!
