{"record":{"id":"9b8cb0291f45b97a","repo":"Tencent/WeKnora","slug":"failed-to-delete-chunks-w","errorCode":null,"errorMessage":"failed to delete chunks: %w","messagePattern":"failed to delete chunks: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/knowledge_faq_import.go","lineNumber":1420,"sourceCode":"\t\t// Replace模式：计算需要删除、创建、更新的条目\n\t\tentriesToProcess, chunksToDelete, skippedCount, err = s.calculateReplaceOperations(\n\t\t\tctx,\n\t\t\ttenantID,\n\t\t\tfaqKnowledge.ID,\n\t\t\tpayload.Entries,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to calculate replace operations: %w\", err)\n\t\t}\n\n\t\t// 删除需要删除的chunks（包括需要更新的旧chunks）\n\t\tif len(chunksToDelete) > 0 {\n\t\t\tchunkIDsToDelete := make([]string, 0, len(chunksToDelete))\n\t\t\tfor _, chunk := range chunksToDelete {\n\t\t\t\tchunkIDsToDelete = append(chunkIDsToDelete, chunk.ID)\n\t\t\t}\n\t\t\tif err := s.chunkRepo.DeleteChunks(ctx, tenantID, chunkIDsToDelete); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to delete chunks: %w\", err)\n\t\t\t}\n\t\t\t// 删除索引\n\t\t\tif err := s.deleteFAQChunkVectors(ctx, kb, faqKnowledge, chunksToDelete); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to delete chunk vectors: %w\", err)\n\t\t\t}\n\t\t\tlogger.Infof(ctx, \"FAQ import task %s: deleted %d chunks (including updates)\", taskID, len(chunksToDelete))\n\t\t}\n\t} else {\n\t\t// Append 模式（智能合并）：标准问已存在的条目走 merge ops，其余作为新建。\n\t\tvar mergeOps []faqMergeOperation\n\t\tentriesToProcess, mergeOps, skippedCount, err = s.calculateAppendOperations(ctx, tenantID, kb.ID, payload.Entries)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to calculate append operations: %w\", err)\n\t\t}\n\n\t\tif len(mergeOps) > 0 {\n\t\t\tmergedCount, mergeErr := s.executeFAQMergeOperations(ctx, taskID, kb, faqKnowledge, embeddingModel, indexMode, mergeOps, progress)\n\t\t\tif mergeErr != nil {","sourceCodeStart":1402,"sourceCodeEnd":1438,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/knowledge_faq_import.go#L1402-L1438","documentation":"executeFAQImport wraps errors from chunkRepo.DeleteChunks when bulk-deleting chunks that must be removed or replaced in replace-mode import. Deletion happens before vector cleanup, so a failure here leaves old vectors in the index but no DB chunks. The cause is the repository/DB error preserved by %w.","triggerScenarios":"Replace-mode import computes a non-empty chunksToDelete list; DeleteChunks fails due to DB outage, transaction/lock timeout, foreign-key constraint, or context cancellation.","commonSituations":"Deadlocks with concurrent imports on the same knowledge base; FK constraints referencing chunk IDs; DB connection drop mid-batch-delete; overly large batch exceeding statement limits.","solutions":["Inspect the wrapped cause (constraint violation vs connectivity vs timeout)","Retry the import; DeleteChunks is usually safe to re-attempt as part of the idempotent replace flow","Check for FK constraints/locks on chunks and chunk batch size limits","Serialize imports per knowledge base to avoid concurrent-delete deadlocks"],"exampleFix":"// before\nif err := s.chunkRepo.DeleteChunks(ctx, tenantID, chunkIDsToDelete); err != nil {\n\treturn fmt.Errorf(\"failed to delete chunks: %w\", err)\n}\n// after\nif err := s.chunkRepo.DeleteChunks(ctx, tenantID, chunkIDsToDelete); err != nil {\n\treturn fmt.Errorf(\"failed to delete %d chunks (task %s): %w\", len(chunkIDsToDelete), taskID, err)\n}","handlingStrategy":"retry","validationCode":"// Preflight: ensure no concurrent task is mutating the same knowledge base\nlocked, err := acquireImportLock(ctx, redisClient, \"faq-import:\"+kbID, ttl)\nif err != nil || !locked {\n\treturn fmt.Errorf(\"another FAQ import is running for this knowledge base\")\n}\ndefer releaseImportLock(redisClient, \"faq-import:\"+kbID)","typeGuard":null,"tryCatchPattern":"err := runReplaceImport(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"failed to delete chunks\") {\n\tif errors.Is(err, context.DeadlineExceeded) || isDeadlock(err) {\n\t\treturn retryWithBackoff(3, runReplaceImport, ctx, req)\n\t}\n\treturn err // constraint errors need manual/data-model fix\n}\nreturn err","preventionTips":["Batch DeleteChunks calls below DB statement size limits","Serialize imports per knowledge base with a distributed lock","Check FK constraints on chunk IDs before enabling replace mode","Set lock_timeout/idle-in-transaction timeouts appropriate for bulk deletes"],"tags":["database","faq-import","delete"],"backgroundTag":"bulk-delete-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}