unslothai/unsloth · error
${label} did not report completion: the connection closed be
Error message
${label} did not report completion: the connection closed before the server's reply arrived. Check the model's status before retrying. What it means
assertCompletedPaddedBody validates that a padded (non-streaming) response body is a non-empty, non-array object — the protocol's completion marker. An empty object, null, array, primitive, or empty body means the connection closed before the server's reply arrived, mirroring the backend check require_completed_padded_body in unsloth_cli/_inference.py. The label names which operation failed.
Source
Thrown at studio/frontend/src/features/chat/api/padded-response.ts:22
/**
* `/api/inference/load` and `/unload` pad their body so a proxy cannot time the request
* out, committing the 200 before the work finishes (`_tunnel_safe_json` in
* studio/backend/routes/inference.py). A proxy giving up mid-pad leaves a 200 with an
* empty or truncated body; accepting that reports an unfinished load as done. Only
* these two routes commit that early, so only they require a payload; elsewhere an
* empty body is by design. Mirrored by `require_completed_padded_body` in
* unsloth_cli/_inference.py.
*/
export function assertCompletedPaddedBody(body: unknown, label: string): void {
const complete =
typeof body === "object" &&
body !== null &&
!Array.isArray(body) &&
Object.keys(body).length > 0;
if (complete) {
return;
}
throw new Error(
`${label} did not report completion: the connection closed before the server's reply arrived. Check the model's status before retrying.`,
);
}
View on GitHub (pinned to 203007d190)
Solutions
- Check the model server's status/logs — the message explicitly says the reply never arrived, so the server side is the suspect.
- Look for proxy response-size/time limits truncating the body.
- Retry the request once the model is healthy (the error is safe to retry — no side effects).
- If it persists, verify the frontend and backend padding-protocol versions match (require_completed_padded_body mirror).
Defensive patterns
Strategy: retry
Validate before calling
import { assertCompletedPaddedBody } from './padded-response';
// Pre-flight the model is accepting requests before a long padded call
if (!(await modelHealthcheck())) throw new Error('Model not ready'); Type guard
function isPaddedBodyIncomplete(e: unknown): boolean {
return e instanceof Error && e.message.includes('did not report completion');
} Try / catch
try { assertCompletedPaddedBody(body, label); }
catch (e) {
if (isPaddedBodyIncomplete(e) && attempt < 2) { await backoff(attempt); return requestAgain(); }
throw e;
} Prevention
- Padded calls are side-effect free — make them idempotent and restartable.
- Monitor model-server health and route around unhealthy instances.
- Keep the frontend assert in lockstep with require_completed_padded_body on version bumps.
When it happens
Trigger: Calling a padded/non-stream endpoint whose proxy or server returns an empty body (200 with no content, or truncated JSON parsed to null) — e.g. model server crashed after accepting the request, or a gateway timed out and returned an empty 200.
Common situations: Model server OOM/restart mid-inference; reverse proxy buffering and truncating long responses; connection killed after headers but before body; backend version drift where the padding protocol changed.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- embedder returned {len(items)} vectors for {len(chunk)} inpu
- load error: {p.get('error')}
- model load did not reach ready within {timeout_s}s
- load error: {p.get('error')}
- model load did not reach ready
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/45a7015be8875eb2.
Report an issue: GitHub.