{"record":{"id":"abd4267f5df5eb3b","repo":"iflytek/astron-agent","slug":"repo-status-illegal","errorCode":"REPO_STATUS_ILLEGAL","errorMessage":"REPO_STATUS_ILLEGAL","messagePattern":"REPO_STATUS_ILLEGAL","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":595,"sourceCode":"        return knowledgeV2ServiceCallHandler.documentSplit(request, datasetId);\n    }\n\n    /** Return ragflow_dataset_id for Ragflow-RAG; null keeps default dataset routing. */\n    private String resolveRagflowDatasetIdOrNull(FileInfoV2 fileInfoV2) {\n        return resolveRagflowDatasetIdOrNull(fileInfoV2, null);\n    }\n\n    /** Same resolver with an optional repoId -> datasetId cache. */\n    private String resolveRagflowDatasetIdOrNull(FileInfoV2 fileInfoV2,\n            Map<Long, String> repoIdToDatasetId) {\n        if (!ProjectContent.FILE_SOURCE_RAG_FLOW_RAG_STR.equals(fileInfoV2.getSource())) {\n            return null;\n        }\n        Long repoId = fileInfoV2.getRepoId();\n        if (repoId == null) {\n            log.error(\"Ragflow-RAG file requires repoId on FileInfoV2 id={}\",\n                    fileInfoV2.getId());\n            throw new BusinessException(ResponseEnum.REPO_STATUS_ILLEGAL);\n        }\n        if (repoIdToDatasetId != null && repoIdToDatasetId.containsKey(repoId)) {\n            // Preserve cached null values for repos without ragflowDatasetId.\n            return repoIdToDatasetId.get(repoId);\n        }\n        Repo repo = repoService.getById(repoId);\n        if (repo == null) {\n            log.error(\"Repo not found for repoId={}\", repoId);\n            throw new BusinessException(ResponseEnum.REPO_STATUS_ILLEGAL);\n        }\n        String datasetId = repo.getRagflowDatasetId();\n        if (repoIdToDatasetId != null) {\n            repoIdToDatasetId.put(repoId, datasetId);\n        }\n        return datasetId;\n    }\n\n    private boolean applyRagflowDatasetIdForDelete(KnowledgeRequest request, FileInfoV2 fileInfoV2) {","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/KnowledgeService.java#L577-L613","documentation":"BusinessException REPO_STATUS_ILLEGAL thrown by resolveRagflowDatasetIdOrNull when a file whose source is Ragflow-RAG has a null repoId on its FileInfoV2 record. For Ragflow-RAG sources the repoId is mandatory because dataset routing is resolved via the owning Repo; without it the resolver cannot determine which ragflow dataset to target.","triggerScenarios":"Any document split/delete path (e.g., doUrlSplit, applyRagflowDatasetIdForDelete) on a FileInfoV2 where source == FILE_SOURCE_RAG_FLOW_RAG_STR but repoId is null. Typically caused by files imported/copied without repoId, or Ragflow source set on a file created by a flow that does not assign a repo.","commonSituations":"Data migration or script inserted Ragflow-RAG files without setting repo_id. A repo was unbound and repoId zeroed out. Code newly introduced the Ragflow-RAG requirement while legacy rows predate it. Note: applyRagflowDatasetIdForDelete catches this exception and skips delete, but split paths let it propagate.","solutions":["Fix the data: UPDATE file_info_v2 SET repo_id = <correct repo id> WHERE id = <fileId> for Ragflow-RAG files.","Ensure the file creation/import flow always sets repoId when source is Ragflow-RAG; add a validation on write.","If the file is not truly Ragflow-RAG, correct the source field so the resolver short-circuits to null.","Audit legacy rows: SELECT id FROM file_info_v2 WHERE source='ragflow' AND repo_id IS NULL."],"exampleFix":"// before\nLong repoId = fileInfoV2.getRepoId(); // null -> REPO_STATUS_ILLEGAL\n// after (guard at write time)\nif (ProjectContent.FILE_SOURCE_RAG_FLOW_RAG_STR.equals(fileInfoV2.getSource()) && fileInfoV2.getRepoId() == null) {\n    throw new IllegalArgumentException(\"repoId required for Ragflow-RAG file \" + fileInfoV2.getId());\n}\nfileInfoV2Service.save(fileInfoV2);","handlingStrategy":"validation","validationCode":"if (ProjectContent.FILE_SOURCE_RAG_FLOW_RAG_STR.equals(fileInfoV2.getSource())) {\n    if (fileInfoV2.getRepoId() == null) { repairRepoIdOrReject(fileInfoV2); }\n}","typeGuard":null,"tryCatchPattern":"try { datasetId = resolveRagflowDatasetIdOrNull(fileInfoV2); } catch (BusinessException e) { log.warn(\"invalid ragflow metadata, using default routing\"); datasetId = null; }","preventionTips":["Always set repo_id when writing Ragflow-RAG FileInfoV2 rows.","Add a NOT NULL constraint or application-level check for repo_id on ragflow-source files.","Audit legacy rows after enabling Ragflow-RAG support."],"tags":["ragflow","rag","data-integrity","java"],"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"}