{"record":{"id":"e4523e4c408a022f","repo":"jeecgboot/JeecgBoot","slug":"id","errorCode":null,"errorMessage":"知识库文档ID为空","messagePattern":"知识库文档ID为空","errorType":"exception","errorClass":"JeecgBootBizTipException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/api/AiragBaseApiImpl.java","lineNumber":51,"sourceCode":"    @Override\n    public String knowledgeWriteTextDocument(String knowledgeId, String title, String content, String segmentConfig) {\n        AssertUtils.assertNotEmpty(\"知识库ID不能为空\", knowledgeId);\n        AssertUtils.assertNotEmpty(\"写入内容不能为空\", content);\n        AiragKnowledgeDoc knowledgeDoc = new AiragKnowledgeDoc();\n        knowledgeDoc.setKnowledgeId(knowledgeId);\n        knowledgeDoc.setTitle(title);\n        knowledgeDoc.setType(LLMConsts.KNOWLEDGE_DOC_TYPE_TEXT);\n        knowledgeDoc.setContent(content);\n        // 将分段策略配置写入文档的metadata中，EmbeddingHandler会从中读取分段配置\n        if (oConvertUtils.isNotEmpty(segmentConfig)) {\n            knowledgeDoc.setMetadata(segmentConfig);\n        }\n        Result<?> result = airagKnowledgeDocService.editDocument(knowledgeDoc);\n        if (!result.isSuccess()) {\n            throw new JeecgBootBizTipException(result.getMessage());\n        }\n        if (knowledgeDoc.getId() == null) {\n            throw new JeecgBootBizTipException(\"知识库文档ID为空\");\n        }\n        log.info(\"[AI-KNOWLEDGE] 文档写入完成，知识库:{}, 文档ID:{}\", knowledgeId, knowledgeDoc.getId());\n        return knowledgeDoc.getId();\n    }\n\n    @Autowired\n    private IAiragAppService airagAppService;\n\n    @Autowired\n    private IAiragVariableService airagVariableService;\n\n    @Autowired\n    private IAiragPromptsService airagPromptsService;\n\n    @Override\n    public String getChatVariable(String appId, String username, String name) {\n        return airagVariableService.getVariable(username, appId, name);\n    }","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/api/AiragBaseApiImpl.java#L33-L69","documentation":"This error is thrown when airagKnowledgeDocService.editDocument() succeeds (returns a success Result) but the knowledgeDoc object's ID remains null after the operation. This indicates the service accepted the document but did not assign or populate an ID, which is an internal consistency failure. The caller (knowledgeWriteTextDocument) needs the ID to return it.","triggerScenarios":"A call to knowledgeWriteTextDocument() where editDocument returns success but does not set the ID on the knowledgeDoc entity. This can happen if the service implementation uses a different entity instance internally, if the ID generation strategy fails, or if the insert/update logic has a bug that doesn't populate the generated key back.","commonSituations":"MyBatis-Plus ID generation strategy (IdType.ASSIGN_ID) fails due to Snowflake worker configuration issues. The service implementation creates a new entity internally and doesn't copy the ID back. A database insert succeeded but the generated key wasn't returned due to JDBC driver behavior. The entity's @TableId annotation is misconfigured.","solutions":["Check the AiragKnowledgeDoc entity's @TableId annotation and ensure IdType is correctly configured.","Verify the Snowflake/ID generation worker configuration is valid (worker ID within range, datacenter ID within range).","Debug the editDocument service implementation to confirm the ID is set on the entity after insert.","Check database logs to see if the insert actually succeeded and what ID was generated."],"exampleFix":"// before — relying on the passed-in object to have its ID populated\nResult<?> result = airagKnowledgeDocService.editDocument(knowledgeDoc);\nif (knowledgeDoc.getId() == null) {\n    throw new JeecgBootBizTipException(\"知识库文档ID为空\");\n}\n\n// after — query back for the document to obtain the ID\nResult<?> result = airagKnowledgeDocService.editDocument(knowledgeDoc);\nif (knowledgeDoc.getId() == null && result.getResult() instanceof AiragKnowledgeDoc) {\n    knowledgeDoc.setId(((AiragKnowledgeDoc) result.getResult()).getId());\n}\nif (knowledgeDoc.getId() == null) {\n    throw new JeecgBootBizTipException(\"知识库文档ID为空\");\n}","handlingStrategy":"try-catch","validationCode":"// Before relying on the returned ID, verify the service populated it\nAiragKnowledgeDoc doc = new AiragKnowledgeDoc();\ndoc.setKnowledgeId(knowledgeId);\n// ... set fields\nResult<?> result = service.editDocument(doc);\nif (result.isSuccess() && doc.getId() == null) {\n    // Query back using knowledge ID + title to find the created document\n    log.warn(\"editDocument succeeded but ID is null; attempting recovery query\");\n}","typeGuard":"public static boolean hasValidId(AiragKnowledgeDoc doc) {\n    return doc != null && doc.getId() != null && !doc.getId().isEmpty();\n}","tryCatchPattern":"try {\n    String docId = airagBaseApi.knowledgeWriteTextDocument(knowledgeId, title, content, segmentConfig);\n    return docId;\n} catch (JeecgBootBizTipException e) {\n    if (\"知识库文档ID为空\".equals(e.getMessage())) {\n        // Document was created but ID wasn't returned — investigate service impl\n        log.error(\"ID population failed after successful editDocument for knowledgeId={}\", knowledgeId);\n    }\n    throw e;\n}","preventionTips":["Verify AiragKnowledgeDoc entity has @TableId(type = IdType.ASSIGN_ID) properly set","Check the editDocument service implementation to ensure it sets the ID after insert","Add integration tests that verify ID population after document creation","Monitor for this error in production as it indicates a data integrity issue"],"tags":["airag","knowledge-base","data-integrity","mybatis"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}