apolloconfig/apollo · error · ServiceException
Write error. {}
Error message
Write error. {} What it means
Thrown by ConfigsExportService.writeClusterInfoToZip() when serializing a ClusterDTO to JSON and writing it as a ZipEntry fails with an IOException. The cluster consumer iterates over exportClusters, generates a cluster-info file path, and calls writeToZip inside a synchronized block on the ZipOutputStream. A single IOException aborts the whole cluster export via ServiceException.
Source
Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/service/ConfigsExportService.java:325
}
};
configBOStream.forEach(configBOConsumer);
}
private void writeClusterInfoToZip(Env env, App app, List<ClusterDTO> exportClusters,
ZipOutputStream zipOutputStream) {
final Consumer<ClusterDTO> clusterConsumer = cluster -> {
try {
synchronized (zipOutputStream) {
String fileName = ConfigFileUtils.genClusterInfoPath(app, env, cluster);
String content = gson.toJson(cluster);
writeToZip(fileName, content, zipOutputStream);
}
} catch (IOException e) {
logger.error("Write error. {}", cluster);
throw new ServiceException("Write error. {}", e);
}
};
exportClusters.forEach(clusterConsumer);
}
private void writeToZip(String filePath, String content, ZipOutputStream zipOutputStream)
throws IOException {
final ZipEntry zipEntry = new ZipEntry(filePath);
try {
zipOutputStream.putNextEntry(zipEntry);
zipOutputStream.write(content.getBytes());
zipOutputStream.closeEntry();
} catch (IOException e) {
String errorMsg = "write content to zip error. file = " + filePath + ", content = " + content;
logger.error(errorMsg);
throw new IOException(errorMsg, e);
}View on GitHub (pinned to d95fc18d11)
Solutions
- Review portal logs for the 'Write error. {cluster}' line to identify the failing ClusterDTO and the IOException cause.
- Confirm the export ZipOutputStream lifecycle: it must remain open until all consumers (app, namespace, cluster) finish.
- Check server disk space and client connection stability during large multi-cluster exports.
- Ensure exportClusters is not invoked on an already-finished or closed stream from a prior failed export stage.
Defensive patterns
Strategy: try-catch
Try / catch
try {
configsExportService.writeClusterInfoToZip(env, app, clusters, zipOutputStream);
} catch (ServiceException e) {
log.error("Cluster info write to zip failed", e);
throw e;
} Prevention
- Validate the ZipOutputStream is not finished or closed before calling writeClusterInfoToZip.
- Ensure cluster export runs as part of a single open-stream lifecycle.
- Handle client disconnects gracefully to avoid partial zip corruption.
When it happens
Trigger: Exporting cluster metadata where writeToZip() encounters a closed/finished ZipOutputStream, a client-disconnected response stream, or a disk-full condition. The synchronized block ensures thread safety but any I/O failure inside it throws and propagates out of forEach.
Common situations: Client cancels the export download; portal container disk full; ZipOutputStream.finish() invoked early by a prior error handler; concurrent export of the same env producing interleaved close/write.
Related errors
- export app config error
- Write app error. {}
- Write namespace error. {}
- export config error
- import configs failed: %s
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/a4ff1afdc404d895.
Report an issue: GitHub.