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

  1. Check server logs for the underlying IOException (often 'Broken pipe' meaning the client disconnected — usually harmless).
  2. Reduce export size (paginate, limit rows) so downloads complete before proxy/browser timeouts.
  3. Verify reverse-proxy timeout settings (e.g. nginx proxy_read_timeout) exceed export generation time.
  4. 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

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


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)