{"record":{"id":"d050558edd3163b6","repo":"iflytek/astron-agent","slug":"repo-knowledge-splitting","errorCode":"REPO_KNOWLEDGE_SPLITTING","errorMessage":"REPO_KNOWLEDGE_SPLITTING","messagePattern":"REPO_KNOWLEDGE_SPLITTING","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":1393,"sourceCode":"     * Parse failure retry: Reset/write directory tree → Validate range/separators → Set status to\n     * parsing → Execute slicing asynchronously (auto-trigger subsequent embedding)\n     *\n     * @param file file information object\n     * @param vo deal file parameters\n     * @param spaceId space ID for permission checking\n     * @param pool thread pool for async execution\n     * @throws BusinessException if file is currently being parsed or range is invalid\n     */\n    private void handleParseFailedRetry(FileInfoV2 file, DealFileVO vo, Long spaceId, ExecutorService pool) {\n        SliceConfig sc = normalizeAndValidateSliceConfig(vo);\n\n        // Permission validation (consistent with original logic: validate only when spaceId is null)\n        if (spaceId == null)\n            dataPermissionCheckTool.checkFileBelong(file);\n\n        // Prohibit retry if currently parsing\n        if (Objects.equals(file.getStatus(), ProjectContent.FILE_PARSE_DOING)) {\n            throw new BusinessException(ResponseEnum.REPO_KNOWLEDGE_SPLITTING);\n        }\n\n        // AIUI slice range validation\n        validateSliceRangeForAiui(sc, file.getSource());\n\n        // Ensure directory tree existence\n        ensureFileDirectoryTree(file);\n\n        // Update slice configuration & set status to parsing\n        file.setSliceConfig(JSON.toJSONString(sc));\n        file.setCurrentSliceConfig(JSON.toJSONString(sc));\n        file.setStatus(ProjectContent.FILE_PARSE_DOING);\n        fileInfoV2Mapper.updateById(file);\n\n        // Execute slicing task asynchronously (with backEmbedding flag set to 1)\n        pool.execute(() -> new SliceFileTask(this, file.getId(), sc, 1).call());\n    }\n","sourceCodeStart":1375,"sourceCodeEnd":1411,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/FileInfoV2Service.java#L1375-L1411","documentation":"FileInfoV2Service throws REPO_KNOWLEDGE_SPLITTING when a retry is requested for a file whose current status is FILE_PARSE_DOING. The file is already being parsed/sliced, so starting another retry would race with the in-flight job; the service refuses with this business error instead.","triggerScenarios":"Calling retry for a file whose DB row has status == ProjectContent.FILE_PARSE_DOING — i.e. a parse/slice job is currently running for that file.","commonSituations":"Double-clicking the retry button so the second request lands while the first is still processing; an async slice job is stuck in DOING status from a previous crash; polling UI retrying automatically before status flips to done/failed.","solutions":["Wait for the current parse to finish (poll the file status) before retrying.","If the status is stuck in DOING with no running job (e.g. after a crash), reset the file status to failed/idle in the DB or via an admin path, then retry.","Debounce/disable the retry button in the UI while file status is 'parsing'."],"exampleFix":"// before\nfileInfoV2Service.retry(vo, request); // may hit FILE_PARSE_DOING\n// after\nFile file = fileMapper.selectById(fileId);\nif (ProjectContent.FILE_PARSE_DOING.equals(file.getStatus())) {\n    throw new IllegalStateException(\"file \" + fileId + \" is still parsing; retry later\");\n}\nfileInfoV2Service.retry(vo, request);","handlingStrategy":"validation","validationCode":"File f = fileMapper.selectById(fileId);\nif (f != null && ProjectContent.FILE_PARSE_DOING.equals(f.getStatus())) {\n    throw new IllegalStateException(\"file is currently parsing; wait before retry\");\n}","typeGuard":"boolean isParsing(File file) {\n    return file != null && Objects.equals(file.getStatus(), ProjectContent.FILE_PARSE_DOING);\n}","tryCatchPattern":"try {\n    fileInfoV2Service.retry(vo, request);\n} catch (BusinessException e) {\n    if (e.getResponseEnum() == ResponseEnum.REPO_KNOWLEDGE_SPLITTING) {\n        // poll status until done/failed, then retry\n        awaitFileStatus(fileId, Duration.ofMinutes(5));\n        fileInfoV2Service.retry(vo, request);\n    } else { throw e; }\n}","preventionTips":["Disable retry buttons while the file status is 'parsing'.","Add a stuck-status watchdog to reset FILE_PARSE_DOING rows whose jobs died.","Serialize retries per file (lock/idempotency key) to prevent duplicate submissions."],"tags":["java","spring-boot","state-conflict","concurrency"],"backgroundTag":"invalid-state-transition","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"}