{"record":{"id":"72ab06989547f518","repo":"gitbutlerapp/gitbutler","slug":"received-empty-response-from-ai-service","errorCode":null,"errorMessage":"Received empty response from AI service","messagePattern":"Received empty response from AI service","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"apps/desktop/src/components/settings/AiCredentialCheck.svelte","lineNumber":149,"sourceCode":"\t\t\t\t\t// Append each token as it comes in\n\t\t\t\t\tstreamingResult += token;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\t// Clear the timeout since we got a result\n\t\t\tif (testTimeout) {\n\t\t\t\tclearTimeout(testTimeout);\n\t\t\t\ttestTimeout = null;\n\t\t\t}\n\n\t\t\t// Set the final result (handling undefined case)\n\t\t\tresult = aiResult || streamingResult || null;\n\n\t\t\tdebugInfo += `, Received commit message: ${result?.substring(0, 30)}${result && result.length > 30 ? \"...\" : \"\"}`;\n\n\t\t\t// If result is empty or undefined, show an error\n\t\t\tif (!result || result.trim() === \"\") {\n\t\t\t\tthrow new Error(\"Received empty response from AI service\");\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error(\"AI credential check error:\", e);\n\n\t\t\t// Don't show abort errors as they're expected when we cancel the request\n\t\t\tif (e instanceof Error && e.name === \"AbortError\") {\n\t\t\t\terror = \"AI request was cancelled\";\n\t\t\t} else {\n\t\t\t\terror = e instanceof Error ? e.message : \"Unknown error occurred\";\n\t\t\t}\n\n\t\t\tdebugInfo += `, Error: ${error}`;\n\n\t\t\t// Clear the timeout if there was an error\n\t\t\tif (testTimeout) {\n\t\t\t\tclearTimeout(testTimeout);\n\t\t\t\ttestTimeout = null;\n\t\t\t}","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/apps/desktop/src/components/settings/AiCredentialCheck.svelte#L131-L167","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const candidate = aiResult || streamingResult || \"\";\nif (candidate.trim() === \"\") {\n  // retry once before surfacing the error to the user\n  retried = true;\n  await generate();\n}","typeGuard":null,"tryCatchPattern":"try {\n  await runCheck();\n} catch (e) {\n  if (e instanceof Error && e.message === \"Received empty response from AI service\" && !retriedOnce) {\n    retriedOnce = true;\n    await runCheck(); // local models often return an empty completion once\n  } else {\n    error = e instanceof Error ? e.message : \"Unknown error occurred\";\n  }\n}","preventionTips":["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."],"tags":["gitbutler","ai","empty-response","settings"],"backgroundTag":"empty-ai-response","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}