{"record":{"id":"560e813ab6afeeeb","repo":"apache/iceberg","slug":"s-doesn-t-implement-cleanexpiredmetadata","errorCode":null,"errorMessage":"%s doesn't implement cleanExpiredMetadata","messagePattern":"(.+?) doesn't implement cleanExpiredMetadata","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/ExpireSnapshots.java","lineNumber":161,"sourceCode":"   * <p>Consider {@link CleanupLevel#NONE} when data and metadata files may be more efficiently\n   * removed using a distributed framework through the actions API.\n   *\n   * @param level the cleanup level to use for expired snapshots\n   * @return this for method chaining\n   */\n  default ExpireSnapshots cleanupLevel(CleanupLevel level) {\n    throw new UnsupportedOperationException(\n        this.getClass().getName() + \" doesn't implement cleanupLevel\");\n  }\n\n  /**\n   * Enable cleaning up unused metadata, such as partition specs, schemas, etc.\n   *\n   * @param clean remove unused partition specs, schemas, or other metadata when true\n   * @return this for method chaining\n   */\n  default ExpireSnapshots cleanExpiredMetadata(boolean clean) {\n    throw new UnsupportedOperationException(\n        this.getClass().getName() + \" doesn't implement cleanExpiredMetadata\");\n  }\n}\n","sourceCodeStart":143,"sourceCodeEnd":165,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/ExpireSnapshots.java#L143-L165","documentation":"ExpireSnapshots.cleanExpiredMetadata is a default interface method that throws unless the implementation supports deleting unused metadata (old partition specs, schemas). The default preserves compatibility with implementations written before the option existed.","triggerScenarios":"Calling expireSnapshots.cleanExpiredMetadata(true) on an implementation that does not override it; invoked from expireFiles/call paths when configuration requests metadata cleanup on an unsupported implementation.","commonSituations":"Enabling metadata cleanup on an older Spark/Flink action version or a custom catalog implementation; property-driven configuration (e.g. clean-expired-metadata) reaching a legacy implementation.","solutions":["Upgrade the ExpireSnapshots implementation to one supporting cleanExpiredMetadata","Disable the metadata cleanup option so the default method is never invoked","If you own the implementation, override cleanExpiredMetadata(boolean) and wire it into the expire plan"],"exampleFix":"// before\nexpireSnapshots.cleanExpiredMetadata(true).execute();\n// after\nexpireSnapshots.execute(); // metadata cleanup unsupported by this implementation","handlingStrategy":"try-catch","validationCode":"// gate metadata cleanup on implementation support\ncleanMetadata = cleanMetadata && implementationSupportsMetadataCleanup;","typeGuard":null,"tryCatchPattern":"try {\n  expireSnapshots.cleanExpiredMetadata(true);\n} catch (UnsupportedOperationException e) {\n  LOG.warn(\"cleanExpiredMetadata unsupported, continuing without it\");\n}","preventionTips":["Only enable clean-expired-metadata options with implementations that support them","Catch UnsupportedOperationException around chained option setters","Test expire actions against the exact catalog/engine versions in production"],"tags":["java","api","unsupported-operation"],"backgroundTag":"method-not-implemented","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"}