{"record":{"id":"eccf29b927cb5b0a","repo":"immich-app/immich","slug":"eofexception","errorCode":null,"errorMessage":"EOFException","messagePattern":"EOFException","errorType":"exception","errorClass":"EOFException","httpStatus":null,"severity":"error","filePath":"mobile/android/app/src/main/kotlin/app/alextran/immich/images/RemoteImagesImpl.kt","lineNumber":477,"sourceCode":"          }\n\n          val body = response.body\n            ?: return onFailure(IOException(\"Empty response body\")).also { onComplete() }\n\n          if (call.isCanceled()) {\n            onFailure(OperationCanceledException())\n            return onComplete()\n          }\n\n          body.source().use { source ->\n            val length = body.contentLength().toInt()\n            val buffer = NativeByteBuffer(if (length > 0) length else INITIAL_BUFFER_SIZE)\n            try {\n              if (length > 0) {\n                val wrapped = NativeBuffer.wrap(buffer.pointer, length)\n                while (wrapped.hasRemaining()) {\n                  if (call.isCanceled()) throw OperationCanceledException()\n                  if (source.read(wrapped) == -1) throw EOFException()\n                }\n                buffer.advance(length)\n              } else {\n                while (true) {\n                  if (call.isCanceled()) throw OperationCanceledException()\n                  val bytesRead = source.read(buffer.wrapRemaining())\n                  if (bytesRead == -1) break\n                  buffer.advance(bytesRead)\n                  buffer.ensureHeadroom()\n                }\n              }\n              onSuccess(buffer, response.header(\"Content-Type\"))\n            } catch (e: Exception) {\n              buffer.free()\n              onFailure(e)\n            }\n            onComplete()\n          }","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/mobile/android/app/src/main/kotlin/app/alextran/immich/images/RemoteImagesImpl.kt#L459-L495","documentation":"In RemoteImagesImpl.kt's OkHttp onResponse callback, the response body is streamed into a native buffer. If source.read returns -1 (stream ended) before the expected length has been fully read, an EOFException is thrown — the HTTP response was truncated mid-body.","triggerScenarios":"Server closes the connection after sending fewer bytes than Content-Length promised; interrupted network transfer mid-download of the original image; proxy/load-balancer timeouts cutting the response short.","commonSituations":"Flaky mobile networks during full-quality remote image downloads; Immich server restarts or reverse-proxy (nginx) buffering timeouts; reading via wifi-to-cellular handoff.","solutions":["Retry the download — OkHttp/Call retries or an app-level retry with backoff usually succeeds on a stable connection.","Check server and reverse-proxy timeout/buffering settings (e.g. nginx proxy_read_timeout) so large responses aren't truncated.","Verify server health/logs for connection resets during the transfer.","Consider range-based resumable downloads for large originals."],"exampleFix":"// before\nval bytes = downloadOnce(url)\n// after\nval bytes = runCatching { downloadOnce(url) }.getOrElse { e ->\n  if (e is EOFException) retryWithBackoff(3) { downloadOnce(url) } else throw e\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  downloadAndBuffer(response)\n} catch (e: EOFException) {\n  retryWithBackoff(maxAttempts = 3) { redownload(url) }\n}","preventionTips":["Build app-level retry with backoff for remote media downloads.","Tune reverse-proxy timeouts for large image responses.","Watch for server restarts; resume with range requests when possible."],"tags":["network","okhttp","http","truncated-response","android"],"backgroundTag":"http-request-failed","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}