apolloconfig/apollo · error · ServiceException
export items failed:{}
Error message
export items failed:{} What it means
ServiceException (HTTP 500) from ConfigsExportController single-namespace export when writing the generated config file content to the HttpServletResponse output stream fails. Note the constructor used is ServiceException(String, Exception), so the '{}' in 'export items failed:{}' is NOT formatted (it is Guava-agnostic); the caught Exception is attached as the cause and is where the real detail lives.
Source
Thrown at apollo-portal/src/main/java/com/ctrip/framework/apollo/portal/controller/ConfigsExportController.java:111
// properties file or public namespace has not suffix (.properties)
if (fileNameSplit.size() <= 1
|| !ConfigFileFormat.isValidFormat(fileNameSplit.get(fileNameSplit.size() - 1))) {
fileName = Joiner.on(".").join(namespaceName, ConfigFileFormat.Properties.getValue());
}
NamespaceBO namespaceBO = namespaceService.loadNamespaceBO(appId, Env.valueOf(env), clusterName,
namespaceName, true, false);
// generate a file.
res.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
// file content
final String configFileContent = NamespaceBOUtils.convert2configFileContent(namespaceBO);
try {
// write content to net
res.getOutputStream().write(configFileContent.getBytes());
} catch (Exception e) {
throw new ServiceException("export items failed:{}", e);
}
}
/**
* Export all configs in a compressed file. Just export namespace which current exists read permission. The permission
* check in service.
*/
@PreAuthorize(value = "@unifiedPermissionValidator.isSuperAdmin()")
@GetMapping("/configs/export")
public void exportAll(@RequestParam(value = "envs") String envs, HttpServletRequest request,
HttpServletResponse response) throws IOException {
// filename must contain the information of time
final String filename =
"apollo_config_export_" + DateFormatUtils.format(new Date(), "yyyy_MMdd_HH_mm_ss") + ".zip";
// log who download the configs
logger.info("Download configs, remote addr [{}], remote host [{}]. Filename is [{}]",
request.getRemoteAddr(), request.getRemoteHost(), filename);
// set downloaded filenameView on GitHub (pinned to d95fc18d11)
Solutions
- Read the attached cause Exception in the portal log (it is the real failure, not the '{}' placeholder).
- If it is ClientAbortException / broken pipe, treat as benign (the client left) and add a client-disconnect check before writing.
- Verify the connection/proxy timeouts are large enough for big namespaces.
- Avoid committing the response before the controller writes (no early flush).
Example fix
// before: any I/O failure becomes a 500 ServiceException
try {
res.getOutputStream().write(configFileContent.getBytes());
} catch (Exception e) {
throw new ServiceException("export items failed:{}", e);
}
// after: distinguish a client abort from a real failure, and fix the placeholder
try {
res.getOutputStream().write(configFileContent.getBytes());
} catch (ClientAbortException e) {
log.warn("client aborted export for {}", fileName);
} catch (IOException e) {
throw new ServiceException("export items failed for %s", e, fileName);
} Defensive patterns
Strategy: try-catch
Try / catch
// Export can 500 on client disconnect or backend I/O failure.
try {
portal.exportNamespace(appId, env, cluster, namespace); // downloads file
} catch (HttpServerErrorException e) {
String body = e.getResponseBodyAsString();
if (body.contains("export items failed")) {
// most often a dropped connection; retry once, or surface 'download failed'
log.warn("namespace export failed, possible client disconnect: {}", body);
}
throw e;
} Prevention
- Treat export 500 as transient for client-disconnect cases; retry once.
- Read the cause in portal logs for persistent failures.
- Use a longer proxy/read timeout for large namespaces.
- Do not pre-commit the HTTP response in filters.
When it happens
Trigger: GET /apps/{appId}/envs/{env}/clusters/{clusterName}/namespaces/{namespaceName}/export (single-file export) when res.getOutputStream().write(bytes) throws — client disconnected, broken pipe, container I/O error, or the response is already committed.
Common situations: User cancels the download mid-stream (ClientAbortException); a proxy/load-balancer timing out and closing the connection; the namespace is large and the socket drops; response already committed by a filter.
Related errors
- %s: %s
- namespace not unique
- namespace[appId = %s, cluster= %s] nowCount= %s, maxCount =%
- import configs failed: %s
- import app configs failed: %s
AI-assisted analysis of apolloconfig/apollo@d95fc18d11 (2026-08-14).
Data as JSON: /api/errors/2f7072d79c040f01.
Report an issue: GitHub.