gitbutlerapp/gitbutler · warning · Error
Received empty response from AI service
Error message
Received empty response from AI service
What it means
Thrown after the AI credential check's generation test finishes: result is set from aiResult || streamingResult || null, and if it is null or only whitespace the service technically responded but produced no usable commit message.
Source
Thrown at apps/desktop/src/components/settings/AiCredentialCheck.svelte:149
// Append each token as it comes in
streamingResult += token;
},
});
// Clear the timeout since we got a result
if (testTimeout) {
clearTimeout(testTimeout);
testTimeout = null;
}
// Set the final result (handling undefined case)
result = aiResult || streamingResult || null;
debugInfo += `, Received commit message: ${result?.substring(0, 30)}${result && result.length > 30 ? "..." : ""}`;
// If result is empty or undefined, show an error
if (!result || result.trim() === "") {
throw new Error("Received empty response from AI service");
}
} catch (e) {
console.error("AI credential check error:", e);
// Don't show abort errors as they're expected when we cancel the request
if (e instanceof Error && e.name === "AbortError") {
error = "AI request was cancelled";
} else {
error = e instanceof Error ? e.message : "Unknown error occurred";
}
debugInfo += `, Error: ${error}`;
// Clear the timeout if there was an error
if (testTimeout) {
clearTimeout(testTimeout);
testTimeout = null;
}View on GitHub (pinned to caf1f223d3)
Solutions
- Retry the test once — empty completions from local models are often transient.
- For local backends, verify a model is actually loaded and can answer a trivial prompt (curl the endpoint directly).
- Shorten/repair the prompt source: ensure there are staged changes for the model to describe.
- If it persists, capture the raw provider response in devtools to see whether the service truly returned empty content.
Defensive patterns
Strategy: retry
Validate before calling
const candidate = aiResult || streamingResult || "";
if (candidate.trim() === "") {
// retry once before surfacing the error to the user
retried = true;
await generate();
} Try / catch
try {
await runCheck();
} catch (e) {
if (e instanceof Error && e.message === "Received empty response from AI service" && !retriedOnce) {
retriedOnce = true;
await runCheck(); // local models often return an empty completion once
} else {
error = e instanceof Error ? e.message : "Unknown error occurred";
}
} Prevention
- Retry empty completions once before reporting failure — they are frequently transient.
- For local backends, verify the model is loaded and answers a trivial prompt.
- Keep the existing 20s streaming timeout so silent streams fail fast instead of hanging.
When it happens
Trigger: The test generation call completed (or timed out into an empty stream result) yielding '' or undefined: model returned an empty completion, the stream produced no chunks before finishing, or the response shape changed so both result variables stayed unset.
Common situations: Ollama/LM Studio answered but returned an empty completion (model not loaded, context overflow); hosted API returned an empty choice; content-filtered response; frontend/backend contract drift where the generated text field moved.
Related errors
- Please sign in to use GitButler's AI API
- Please provide a valid API key for your selected AI service
- Please check Ollama configuration: endpoint=${endpoint}, mod
- Please check LM Studio configuration: endpoint=${endpoint}
- Conflicted uncommitted files can only be marked as resolved:
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/72ab06989547f518.
Report an issue: GitHub.