{"record":{"id":"2bee3986f02ded9c","repo":"iflytek/astron-agent","slug":"repo-knowledge-download-failed","errorCode":"REPO_KNOWLEDGE_DOWNLOAD_FAILED","errorMessage":"ResponseEnum.REPO_KNOWLEDGE_DOWNLOAD_FAILED","messagePattern":"ResponseEnum\\.REPO_KNOWLEDGE_DOWNLOAD_FAILED","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/KnowledgeService.java","lineNumber":1382,"sourceCode":"            extractKnowledgeTask.setUpdateTime(timestamp);\n            extractKnowledgeTaskService.updateById(extractKnowledgeTask);\n\n            fileInfoV2.setStatus(ProjectContent.FILE_PARSE_FAILED);\n            fileInfoV2.setReason(errMsg);\n            fileInfoV2.setUpdateTime(timestamp);\n            fileInfoV2Service.updateById(fileInfoV2);\n            return;\n        }\n\n        Repo repo = repoService.getById(fileInfoV2.getRepoId());\n\n\n        String entityBody = null;\n        try {\n            RestTemplate restTemplate = new RestTemplate();\n            ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);\n            if (forEntity.getStatusCode() != HttpStatus.OK) {\n                throw new BusinessException(ResponseEnum.REPO_KNOWLEDGE_DOWNLOAD_FAILED);\n            }\n            entityBody = forEntity.getBody();\n            JSONArray jsonArray = JSON.parseArray(entityBody);\n            List<ChunkInfo> chunkInfos = null;\n            if (repo.getEnableAudit()) {\n                if (jsonArray != null) {\n                    chunkInfos = jsonArray.toJavaList(ChunkInfo.class);\n                }\n            }\n            this.storagePreviewKnowledge(fileInfoV2.getUuid(), fileInfoV2.getId(), chunkInfos);\n\n            extractKnowledgeTask.setStatus(1);\n            extractKnowledgeTask.setUpdateTime(timestamp);\n            extractKnowledgeTaskService.updateById(extractKnowledgeTask);\n\n            fileInfoV2.setStatus(ProjectContent.FILE_PARSE_SUCCESSED);\n            fileInfoV2.setReason(null);\n            fileInfoV2.setUpdateTime(timestamp);","sourceCodeStart":1364,"sourceCodeEnd":1400,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/KnowledgeService.java#L1364-L1400","documentation":"BusinessException REPO_KNOWLEDGE_DOWNLOAD_FAILED thrown by downloadKnowLedgeData when the RestTemplate GET of the knowledgeUrl does not return HTTP 200. The extraction service reports the parsed knowledge chunks at a URL; if downloading that result file fails, the knowledge cannot be stored and the task/file are marked failed in the surrounding catch block.","triggerScenarios":"restTemplate.getForEntity(url, String.class) returning a non-OK status (403 signature/permission expired on object storage, 404 the result file was deleted or the URL expired, 5xx from the storage/extract service). Note RestTemplate throws HttpClientErrorException for 4xx before the status check — the explicit check mostly catches non-2xx responses configured not to throw.","commonSituations":"Presigned/knowledgeUrl expired between extraction completion and callback processing. Object storage (MinIO/S3) credentials or bucket policy changed. Upstream extractor wrote the result to a different location than the URL claims. Network/proxy blocking the internal download.","solutions":["Test the URL directly (curl -I <url>) to see the actual status; 404/403 usually means an expired or wrong object-store link.","Ask the extraction service to regenerate/re-upload the result and re-trigger the callback, or re-run the extraction task.","Check object storage (MinIO/S3) availability and credential validity on the box running this service.","Consider adding retry with backoff around the download for transient 5xx, and verify proxy settings if the URL is external."],"exampleFix":"// before\nResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);\nif (forEntity.getStatusCode() != HttpStatus.OK) {\n    throw new BusinessException(ResponseEnum.REPO_KNOWLEDGE_DOWNLOAD_FAILED);\n}\n// after (retry transient failures)\nResponseEntity<String> forEntity = null;\nfor (int i = 0; i < 3; i++) {\n    try {\n        forEntity = restTemplate.getForEntity(url, String.class);\n        if (forEntity.getStatusCode() == HttpStatus.OK) break;\n    } catch (RestClientException e) {\n        log.warn(\"download attempt {} failed: {}\", i + 1, e.getMessage());\n    }\n}\nif (forEntity == null || forEntity.getStatusCode() != HttpStatus.OK) {\n    throw new BusinessException(ResponseEnum.REPO_KNOWLEDGE_DOWNLOAD_FAILED);\n}","handlingStrategy":"retry","validationCode":"// preflight before trusting the callback\nHttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();\nc.setRequestMethod(\"HEAD\");\nif (c.getResponseCode() != 200) { requestFreshResultUrl(taskId); }","typeGuard":null,"tryCatchPattern":"try { downloadKnowLedgeData(url, task, true, null); } catch (BusinessException | RestClientException e) { log.error(\"knowledge download failed: {}\", e.getMessage()); markTaskFailed(task, e.getMessage()); }","preventionTips":["Use non-expiring internal object-store URLs or refresh presigned links before callback.","Monitor object storage (MinIO/S3) uptime and credentials.","Add retry with backoff for transient 5xx on the result download.","Confirm proxy/firewall allows the console backend to reach the result URL host."],"tags":["http","download","object-storage","network","java"],"backgroundTag":"http-non-200-response","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"}