{"record":{"id":"16673fa16abfe77b","repo":"apache/iceberg","slug":"cannot-serialize-fileio-impl-does-not-expose-co","errorCode":null,"errorMessage":"Cannot serialize FileIO: <impl> does not expose configuration properties","messagePattern":"Cannot serialize FileIO: <impl> does not expose configuration properties","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/io/FileIOParser.java","lineNumber":49,"sourceCode":"\n  private static final String FILE_IO_IMPL = \"io-impl\";\n  private static final String PROPERTIES = \"properties\";\n\n  public static String toJson(FileIO io) {\n    return toJson(io, false);\n  }\n\n  public static String toJson(FileIO io, boolean pretty) {\n    return JsonUtil.generate(gen -> toJson(io, gen), pretty);\n  }\n\n  public static void toJson(FileIO io, JsonGenerator generator) throws IOException {\n    String impl = io.getClass().getName();\n    Map<String, String> properties;\n    try {\n      properties = io.properties();\n    } catch (UnsupportedOperationException e) {\n      throw new IllegalArgumentException(\n          String.format(\n              \"Cannot serialize FileIO: %s does not expose configuration properties\", impl));\n    }\n\n    Preconditions.checkArgument(\n        properties != null,\n        \"Cannot serialize FileIO: invalid configuration properties (null)\",\n        impl);\n\n    generator.writeStartObject();\n\n    generator.writeStringField(FILE_IO_IMPL, impl);\n    JsonUtil.writeStringMap(PROPERTIES, properties, generator);\n\n    generator.writeEndObject();\n  }\n\n  public static FileIO fromJson(String json) {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/io/FileIOParser.java#L31-L67","documentation":"FileIOParser.toJson requires the FileIO to expose its configuration via properties(). FileIO implementations that do not support properties (they throw UnsupportedOperationException) cannot be serialized to JSON, so a descriptive IllegalArgumentException names the offending implementation class.","triggerScenarios":"Calling FileIOParser.toJson(io, generator) (directly or via table metadata / parse of a FileIO that must round-trip) with a FileIO whose properties() throws UnsupportedOperationException, e.g. a custom or minimal FileIO implementation.","commonSituations":"Custom FileIO implementations that don't override properties(); passing a mock or anonymous FileIO into serialization; serializing a table whose io object is not the real catalog-backed implementation.","solutions":["Implement properties() in the custom FileIO to return its configuration map.","Serialize the correct concrete FileIO (e.g. HadoopFileIO / S3FileIO) rather than a wrapper.","If wrapping a FileIO, delegate properties() to the underlying implementation.","Use FileIOUtil or the io() instance from the table/catalog, which is guaranteed serializable."],"exampleFix":"// before\nclass MyFileIO implements FileIO {\n  // no properties() override -> UnsupportedOperationException\n}\n// after\nclass MyFileIO implements FileIO {\n  private final Map<String, String> props;\n  @Override\n  public Map<String, String> properties() { return props; }\n}","handlingStrategy":"try-catch","validationCode":"Map<String, String> props;\ntry { props = io.properties(); } catch (UnsupportedOperationException u) {\n  throw new IllegalArgumentException(\"FileIO \" + io.getClass().getName() + \" not serializable\");\n}","typeGuard":"static boolean jsonSerializable(FileIO io) {\n  try { return io.properties() != null; }\n  catch (UnsupportedOperationException e) { return false; }\n}","tryCatchPattern":"try {\n  FileIOParser.toJson(io, generator);\n} catch (IllegalArgumentException e) {\n  LOG.error(\"FileIO {} cannot be serialized: {}\", io.getClass().getName(), e.getMessage());\n  throw e;\n}","preventionTips":["Always implement properties() in custom FileIO classes","Test custom FileIO round-trips through FileIOParser in unit tests","Don't pass anonymous or mock FileIO instances into serialization paths","Use catalog/table-provided io instances which are known serializable"],"tags":["serialization","fileio","unsupported-operation"],"backgroundTag":"json-serialization-failed","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"}