{"record":{"id":"f677ec5d227bafe6","repo":"apache/iceberg","slug":"failed-to-get-stream-length-no-open-stream","errorCode":null,"errorMessage":"Failed to get stream length: no open stream","messagePattern":"Failed to get stream length: no open stream","errorType":"exception","errorClass":"RuntimeIOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/avro/AvroFileAppender.java","lineNumber":88,"sourceCode":"  }\n\n  @Override\n  public Metrics metrics() {\n    Preconditions.checkState(isClosed, \"Cannot return metrics while appending to an open file.\");\n\n    return AvroMetrics.fromWriter(datumWriter, icebergSchema, numRecords, metricsConfig);\n  }\n\n  @Override\n  public long length() {\n    if (stream != null) {\n      try {\n        return stream.storedLength();\n      } catch (IOException e) {\n        throw new RuntimeIOException(e, \"Failed to get stream length\");\n      }\n    }\n    throw new RuntimeIOException(\"Failed to get stream length: no open stream\");\n  }\n\n  @Override\n  public void close() throws IOException {\n    if (writer != null) {\n      writer.close();\n      this.writer = null;\n      isClosed = true;\n    }\n  }\n\n  @SuppressWarnings(\"unchecked\")\n  private static <D> DataFileWriter<D> newAvroWriter(\n      Schema schema,\n      PositionOutputStream stream,\n      DatumWriter<?> metricsAwareDatumWriter,\n      CodecFactory codec,\n      Map<String, String> metadata)","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/avro/AvroFileAppender.java#L70-L106","documentation":"AvroFileAppender.length() throws RuntimeIOException('Failed to get stream length: no open stream') when called while the appender has no open output stream. This happens before the file is opened or after the appender has been closed and the stream released. Callers must only query length while a stream exists (typically before close).","triggerScenarios":"Calling length() on a freshly constructed AvroFileAppender before any write opened the stream, or after close() has completed; using an appender from the wrong lifecycle stage during commit.","commonSituations":"Custom commit logic querying file length after closing the writer; error-handling paths that inspect length on a never-opened appender; double-close scenarios.","solutions":["Call length() only after the appender has written data (stream is open) and before close()","Capture the file length before closing, or obtain length from the OutputFile after close if the API supports it","Guard the call: check the appender state/lifecycle before querying length","Restructure commit logic so metrics/length are read during the append phase"],"exampleFix":"// before\nappender.close();\nlong len = appender.length(); // no open stream\n\n// after\nlong len = appender.length();\nappender.close();","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"boolean canQueryLength = appenderOpen && !appenderClosed; // track lifecycle in wrapper","tryCatchPattern":"try { return appender.length(); } catch (RuntimeIOException e) { if (e.getMessage().contains(\"no open stream\")) { /* fix lifecycle: capture length before close */ } throw e; }","preventionTips":["Read length() between the first write and close()","Capture file length before closing the appender","Avoid double-close paths in commit code"],"tags":["avro","io","lifecycle","stream"],"backgroundTag":"invalid-state-transition","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}