{"record":{"id":"0b43907041dea5f2","repo":"iflytek/astron-agent","slug":"repo-file-download-failed","errorCode":"REPO_FILE_DOWNLOAD_FAILED","errorMessage":"REPO_FILE_DOWNLOAD_FAILED","messagePattern":"REPO_FILE_DOWNLOAD_FAILED","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"warning","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/FileInfoV2Service.java","lineNumber":2541,"sourceCode":"                sb.append(\"\\n\");\n            }\n        }\n        return sb.toString();\n    }\n\n    /* ---------- Output ---------- */\n\n    private void writeWorkbook(HttpServletResponse resp, HSSFWorkbook wb, String filename) {\n        try (ServletOutputStream out = resp.getOutputStream()) {\n            resp.reset();\n            resp.setHeader(\"Content-disposition\",\n                    \"attachment; filename=\" + URLEncoder.encode(filename, StandardCharsets.UTF_8.name()) + \".xls\");\n            resp.setContentType(\"application/msexcel\");\n            wb.write(out);\n            out.flush();\n        } catch (IOException ex) {\n            log.error(\"File download failed\", ex);\n            throw new BusinessException(ResponseEnum.REPO_FILE_DOWNLOAD_FAILED);\n        }\n    }\n\n\n    /**\n     * Get file information list by repository core ID and existing source IDs\n     *\n     * @param repoCoreId repository core identifier\n     * @param existSourceIds list of existing source IDs to filter\n     * @return list of FileInfoV2 objects matching the criteria\n     * @throws BusinessException if file access is denied\n     */\n    public List<FileInfoV2> getFileInfoV2UUIDS(String repoCoreId, List<String> existSourceIds) {\n        List<FileInfoV2> fileInfoV2List = fileInfoV2Mapper.getFileInfoV2UUIDS(repoCoreId, existSourceIds);\n        Long spaceId = SpaceInfoUtil.getSpaceId();\n\n        for (FileInfoV2 fileInfoV2 : fileInfoV2List) {\n            if (null == spaceId) {","sourceCodeStart":2523,"sourceCodeEnd":2559,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/FileInfoV2Service.java#L2523-L2559","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before: any IOException becomes a hard business error\n} catch (IOException ex) {\n    log.error(\"File download failed\", ex);\n    throw new BusinessException(ResponseEnum.REPO_FILE_DOWNLOAD_FAILED);\n}\n// after: client aborts are expected, don't alarm\n} catch (IOException ex) {\n    if (ex.getMessage() != null && ex.getMessage().contains(\"Broken pipe\")) {\n        log.warn(\"client aborted download: {}\", filename);\n        return;\n    }\n    log.error(\"File download failed\", ex);\n    throw new BusinessException(ResponseEnum.REPO_FILE_DOWNLOAD_FAILED);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await repoApi.exportFilesXls(repoCoreId, sourceIds);\n} catch (e) {\n  if (e.code === 'REPO_FILE_DOWNLOAD_FAILED') {\n    // likely client abort or timeout: retry with smaller batch\n    return retryExportInChunks(repoCoreId, sourceIds, 500);\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["java","io","download","excel"],"backgroundTag":"file-write-failed","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}