{"record":{"id":"1c98395845c35f8a","repo":"apache/iceberg","slug":"getclass-getname-does-not-implement-length-1c9839","errorCode":null,"errorMessage":"${getClass().getName()} does not implement length","messagePattern":"(.+?) does not implement length","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/deletes/SortingPositionOnlyDeleteWriter.java","lineNumber":92,"sourceCode":"      Function<CharSequence, PositionDeleteIndex> loadPreviousDeletes) {\n    this.writers = writers;\n    this.granularity = granularity;\n    this.positionsByPath = CharSequenceMap.create();\n    this.loadPreviousDeletes = loadPreviousDeletes;\n  }\n\n  @Override\n  public void write(PositionDelete<T> positionDelete) {\n    CharSequence path = positionDelete.path();\n    long position = positionDelete.pos();\n    PositionDeleteIndex positions =\n        positionsByPath.computeIfAbsent(path, key -> new BitmapPositionDeleteIndex());\n    positions.delete(position);\n  }\n\n  @Override\n  public long length() {\n    throw new UnsupportedOperationException(getClass().getName() + \" does not implement length\");\n  }\n\n  @Override\n  public DeleteWriteResult result() {\n    return result;\n  }\n\n  @Override\n  public void close() throws IOException {\n    if (result == null) {\n      switch (granularity) {\n        case FILE:\n          this.result = writeFileDeletes();\n          return;\n        case PARTITION:\n          this.result = writePartitionDeletes();\n          return;\n        default:","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/deletes/SortingPositionOnlyDeleteWriter.java#L74-L110","documentation":"SortingPositionOnlyDeleteWriter buffers position-only deletes in memory and sorts them before writing, so it cannot report a stable byte length mid-write; its length() override unconditionally throws UnsupportedOperationException. It is only intended to be queried after result() is obtained.","triggerScenarios":"Calling length() on a SortingPositionOnlyDeleteWriter at any point (including during write), e.g. generic writer code that measures output size before closing the writer.","commonSituations":"Framework or metrics code that uniformly calls writer.length() to track file sizes; the sorting writer's size is unknown until deletes are written on close().","solutions":["Call length() only on the DeleteWriteResult or the produced delete files after writer.close()/result(), not on the writer itself","Check the writer type before querying length, or avoid SortingPositionOnlyDeleteWriter when byte length is needed incrementally","Get the equivalent size from the resulting DeleteFile(s) metadata after commit"],"exampleFix":"// before\nlong len = writer.length();\n// after\nwriter.close();\nlong len = writer.result().deleteFiles().stream().mapToLong(DeleteFile::fileSizeInBytes).sum();","handlingStrategy":"validation","validationCode":"if (writer instanceof SortingPositionOnlyDeleteWriter) { /* do not call length() before close */ }","typeGuard":"boolean supportsLength(DeleteWriter<?> w) { return !(w instanceof SortingPositionOnlyDeleteWriter); }","tryCatchPattern":"try { len = writer.length(); } catch (UnsupportedOperationException e) { len = -1; /* unknown until close */ }","preventionTips":["Query file sizes from DeleteWriteResult/DeleteFile after close, not from the writer","Document writer contracts where length is undefined mid-write","Avoid generic metrics code that assumes all writers implement length()"],"tags":["java","deletes","writer"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}