bytedance/deer-flow · error
Failed to compact context.
Error message
Failed to compact context.
What it means
Thrown when POST .../compact (context compaction) returns non-2xx. The client always sends force:true plus optional agent/model overrides and forwards options.signal so user cancellation aborts the fetch. Backend failures include 404 (unknown thread), 409 (compaction not possible mid-run), 422 (invalid agent_name/model_name), and 504 when compaction of a very long thread exceeds a gateway timeout.
Source
Thrown at frontend/src/core/threads/api.ts:158
): Promise<ThreadCompactResponse> {
const response = await fetchWithAuth(
`${getBackendBaseURL()}/api/threads/${encodeURIComponent(threadId)}/compact`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
force: true,
...(options.agentName ? { agent_name: options.agentName } : {}),
...(options.modelName ? { model_name: options.modelName } : {}),
}),
signal: options.signal,
},
);
if (!response.ok) {
throw new Error(
await readThreadAPIError(response, "Failed to compact context."),
);
}
return (await response.json()) as ThreadCompactResponse;
}
View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Check the wrapped detail: 422 names the invalid agent/model field — pick a valid one from the model list
- Retry after the current run finishes if the conflict is a live run
- On 5xx, verify the configured summarization model works (test a normal chat turn) before retrying compaction
- Use options.signal only for user cancel, and distinguish AbortError from this HTTP error
Example fix
// before
await compactThreadContext(threadId, {agentName});
// after
try {
await compactThreadContext(threadId, {agentName});
} catch (e) {
if (e instanceof Error && /invalid|unknown/i.test(e.message)) {
return compactThreadContext(threadId, {}); // drop bad override
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
async function compactionOptionsValid(options: CompactThreadContextOptions): Promise<boolean> {
if (!options.agentName && !options.modelName) return true;
const models = await loadModelList();
return (!options.agentName || models.agents.includes(options.agentName)) &&
(!options.modelName || models.names.includes(options.modelName));
} Type guard
export function isCompactError(e: unknown): e is Error {
return e instanceof Error && e.message.includes('Failed to compact context.');
} Try / catch
try {
return await compactThreadContext(threadId, options);
} catch (e) {
if (isCompactError(e) && /invalid|unknown/i.test(e.message)) {
return compactThreadContext(threadId, {}); // drop bad overrides
}
if (isCompactError(e) && /conflict|409/i.test(e.message)) {
return retryAfterRunCompletes(threadId, options);
}
throw e;
} Prevention
- Offer only agent/model names from the live config in the UI
- Disable compact while a run is active
- Keep options.signal wired to the cancel button so aborts don't surface as HTTP errors
When it happens
Trigger: Compacting while a run is active on the thread; passing an agent_name or model_name that doesn't exist in config.yaml (422); compacting a thread whose history was already compacted and pruned; LLM backend failure during summarization (500).
Common situations: User clicks 'compact context' on a hot thread; model was renamed in config but the UI still offers the old name; provider API outage during the summarization call.
Related errors
- Failed to create side conversation.
- Failed to load thread token usage.
- Failed to branch conversation.
- Failed to update conversation.
- Failed to load MCP configuration
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/a05e7fde66b84066.
Report an issue: GitHub.