{"id":"7711b1336a0c6ec6","repo":"square/okhttp","slug":"unexpected-code-7711b1","errorCode":null,"errorMessage":"Unexpected code ","messagePattern":"Unexpected code ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"samples/guide/src/main/java/okhttp3/recipes/PostStreamingWithPipe.java","lineNumber":45,"sourceCode":"\npublic final class PostStreamingWithPipe {\n  public static final MediaType MEDIA_TYPE_MARKDOWN\n      = MediaType.get(\"text/x-markdown; charset=utf-8\");\n\n  private final OkHttpClient client = new OkHttpClient();\n\n  public void run() throws Exception {\n    final PipeBody pipeBody = new PipeBody();\n\n    Request request = new Request.Builder()\n        .url(\"https://api.github.com/markdown/raw\")\n        .post(pipeBody)\n        .build();\n\n    streamPrimesToSinkAsynchronously(pipeBody.sink());\n\n    try (Response response = client.newCall(request).execute()) {\n      if (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response);\n\n      System.out.println(response.body().string());\n    }\n  }\n\n  private void streamPrimesToSinkAsynchronously(final BufferedSink sink) {\n    Thread thread = new Thread(\"writer\") {\n      @Override public void run() {\n        try {\n          sink.writeUtf8(\"Numbers\\n\");\n          sink.writeUtf8(\"-------\\n\");\n          for (int i = 2; i <= 997; i++) {\n            System.out.println(i);\n            Thread.sleep(10);\n            sink.writeUtf8(String.format(\" * %s = %s\\n\", i, factor(i)));\n          }\n          sink.close();\n        } catch (IOException | InterruptedException e) {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/square/okhttp/blob/4fc083138014aba3d0078f5c26d1ce84815fa984/samples/guide/src/main/java/okhttp3/recipes/PostStreamingWithPipe.java#L27-L63","documentation":"Recipe-level guard after POSTing a pipe-backed RequestBody to GitHub's markdown/raw endpoint. A separate 'writer' thread feeds the pipe (Okio Pipe of 8192 bytes) while the request thread reads from it in writeTo(). If the server's final HTTP response is non-2xx, java.io.IOException(\"Unexpected code \" + response) is thrown. If the writer thread dies (IOException/InterruptedException in streamPrimesToSinkAsynchronously) the pipe stalls and execute() throws a different IOException, not this line.","triggerScenarios":"POST https://api.github.com/markdown/raw with a PipeBody while a writer thread calls sink.writeUtf8(...)+sink.close(). Reaches this line when both threads cooperated and the upload completed but GitHub returned 4xx/5xx (403 rate limit, 415 media type). A writer-thread crash surfaces as a stuck pipe / connection-reset IOException earlier.","commonSituations":"Writer thread hits InterruptedException (Thread.sleep interrupted) and prints stack trace but does not close the sink cleanly → the request never completes and execute() blocks/fails instead of reaching this line; GitHub rate limiting; mismatched content-type.","solutions":["Ensure the writer thread always closes the sink in a finally block so a stalled pipe cannot hang execute().","Inspect response.code() when you do reach this line; treat as a normal HTTP error.","Authenticate to GitHub and verify the content-type."],"exampleFix":"// before (writer thread)\ntry {\n  ... sink.writeUtf8(...); Thread.sleep(10); ...\n  sink.close();\n} catch (IOException | InterruptedException e) {\n  e.printStackTrace();\n}\n\n// after\ntry {\n  ... sink.writeUtf8(...); ...\n} catch (IOException | InterruptedException e) {\n  e.printStackTrace();\n} finally {\n  try { sink.close(); } catch (IOException ignored) {}\n}\n// and at the response guard:\ntry (Response response = client.newCall(request).execute()) {\n  if (!response.isSuccessful()) {\n    throw new IOException(\"GitHub \" + response.code() + \" after streamed upload\");\n  }\n  ...\n}","handlingStrategy":"try-catch","validationCode":"// Ensure the writer thread always closes the sink so a stalled pipe cannot hang execute()\nThread writer = new Thread(() -> {\n  try (BufferedSink s = sink) {  // try-with-resources guarantees close\n    // ...write payload...\n  } catch (IOException e) {\n    log.warn(\"writer failed\", e);\n  }\n}, \"writer\");\nwriter.setDaemon(true);\nwriter.start();","typeGuard":null,"tryCatchPattern":"try (Response response = client.newCall(request).execute()) {\n  if (!response.isSuccessful()) {\n    throw new HttpException(response.code(), response.message());\n  }\n} catch (IOException e) {\n  // a crashed/unclosed writer thread surfaces here as a pipe stall / connection reset\n  if (writerThread.getState() == Thread.State.TERMINATED) {\n    throw new UploadStallException(\"writer thread died before closing pipe\", e);\n  }\n  throw e;\n}","preventionTips":["Always close the Okio sink in a finally / try-with-resources on the writer thread.","Make the writer thread a daemon so JVM exit is not blocked by a stalled pipe.","Handle InterruptedException by restoring the interrupt status and closing the sink.","Distinguish a writer-thread crash (transport IOException) from an HTTP-error guard."],"tags":["okhttp","http-status","streaming-upload","okio-pipe","threading","post","java"],"analyzedSha":"4fc083138014aba3d0078f5c26d1ce84815fa984","analyzedAt":"2026-08-04T19:09:04.639Z","schemaVersion":2}