iflytek/astron-agent · warning · BusinessException
REPO_FILE_DOWNLOAD_FAILED
REPO_FILE_DOWNLOAD_FAILED
Error message
REPO_FILE_DOWNLOAD_FAILED
What it means
BusinessException(REPO_FILE_DOWNLOAD_FAILED) thrown when writing the generated Excel workbook to the HTTP response output stream throws IOException. The service builds an .xls export (workbook 'wb') and streams it to the servlet response; any I/O failure (client disconnect, broken stream) is converted into this business error.
Solutions
- Check server logs for the underlying IOException (often 'Broken pipe' meaning the client disconnected — usually harmless).
- Reduce export size (paginate, limit rows) so downloads complete before proxy/browser timeouts.
- Verify reverse-proxy timeout settings (e.g. nginx proxy_read_timeout) exceed export generation time.
- Set response headers/commit ordering correctly so the stream is not already closed before wb.write(out).
Example fix
// before: any IOException becomes a hard business error
} catch (IOException ex) {
log.error("File download failed", ex);
throw new BusinessException(ResponseEnum.REPO_FILE_DOWNLOAD_FAILED);
}
// after: client aborts are expected, don't alarm
} catch (IOException ex) {
if (ex.getMessage() != null && ex.getMessage().contains("Broken pipe")) {
log.warn("client aborted download: {}", filename);
return;
}
log.error("File download failed", ex);
throw new BusinessException(ResponseEnum.REPO_FILE_DOWNLOAD_FAILED);
} Defensive patterns
Strategy: try-catch
Try / catch
try {
await repoApi.exportFilesXls(repoCoreId, sourceIds);
} catch (e) {
if (e.code === 'REPO_FILE_DOWNLOAD_FAILED') {
// likely client abort or timeout: retry with smaller batch
return retryExportInChunks(repoCoreId, sourceIds, 500);
}
throw e;
} Prevention
- Chunk large exports to keep response time under proxy timeouts.
- Increase nginx/gateway read timeouts for export endpoints.
- Log the root IOException to distinguish client aborts from server faults.
- Avoid triggering a second export while one is still streaming.
When it happens
Trigger: User cancels/navigates away mid-download closing the socket (broken pipe); response output stream already committed or closed; servlet container aborting the connection; disk/IO errors in the container while flushing.
Common situations: Large exports exceeding gateway/browser timeouts; users clicking away from a slow export; proxy (nginx) cutting the connection on idle timeouts; repeated export clicks creating heavy workbooks.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- Skill resource download failed: HTTP
- Skill resource download returned empty body
- size limit is invalid
- Header mismatch! Expected headers: , Actual headers:
- RESPONSE_FAILED
AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12).
Data as JSON: /api/errors/0b43907041dea5f2.
Report an issue: GitHub.
Appendix: source
Thrown at console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/FileInfoV2Service.java:2541
sb.append("\n");
}
}
return sb.toString();
}
/* ---------- Output ---------- */
private void writeWorkbook(HttpServletResponse resp, HSSFWorkbook wb, String filename) {
try (ServletOutputStream out = resp.getOutputStream()) {
resp.reset();
resp.setHeader("Content-disposition",
"attachment; filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()) + ".xls");
resp.setContentType("application/msexcel");
wb.write(out);
out.flush();
} catch (IOException ex) {
log.error("File download failed", ex);
throw new BusinessException(ResponseEnum.REPO_FILE_DOWNLOAD_FAILED);
}
}
/**
* Get file information list by repository core ID and existing source IDs
*
* @param repoCoreId repository core identifier
* @param existSourceIds list of existing source IDs to filter
* @return list of FileInfoV2 objects matching the criteria
* @throws BusinessException if file access is denied
*/
public List<FileInfoV2> getFileInfoV2UUIDS(String repoCoreId, List<String> existSourceIds) {
List<FileInfoV2> fileInfoV2List = fileInfoV2Mapper.getFileInfoV2UUIDS(repoCoreId, existSourceIds);
Long spaceId = SpaceInfoUtil.getSpaceId();
for (FileInfoV2 fileInfoV2 : fileInfoV2List) {
if (null == spaceId) {View on GitHub (pinned to 5e758547a8)