{"record":{"id":"97e45942a18fd338","repo":"Tencent/WeKnora","slug":"find-conflicting-memory-w","errorCode":null,"errorMessage":"find conflicting memory: %w","messagePattern":"find conflicting memory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/memory/service.go","lineNumber":352,"sourceCode":"\t\t\tctx, scope, item.SourceMessageID, rejectedMessageWindow,\n\t\t)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"check forgotten source: %w\", err)\n\t\t}\n\t}\n\tif forgotten {\n\t\tlogger.Infof(ctx, \"memory: skipped a statement the user previously deleted\")\n\t\treturn nil, ErrPreviouslyForgotten\n\t}\n\tif _, err := s.repo.EnsureSubject(ctx, scope); err != nil {\n\t\treturn nil, fmt.Errorf(\"ensure memory subject: %w\", err)\n\t}\n\n\ttopic := types.SanitizeMemoryTopic(item.Topic)\n\tnormalizedKey := types.MemoryItemKey(topic, content)\n\texisting, err := s.repo.FindActiveByKey(ctx, scope, normalizedKey)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"find conflicting memory: %w\", err)\n\t}\n\tif existing != nil && types.SanitizeMemoryContent(existing.Content) == content {\n\t\t// Same statement about the same topic: nothing changed, so keep the\n\t\t// original timestamps instead of churning the row on every turn.\n\t\treturn existing, nil\n\t}\n\tif existing == nil {\n\t\t// The same fact often arrives twice: once because the user said\n\t\t// \"remember ...\" and again from the background distillation, phrased\n\t\t// slightly differently (\"我们的生产库是 X\" vs \"生产库是 X\"). They get\n\t\t// different topic keys, so key matching alone lets both through and\n\t\t// the user sees their memory duplicated.\n\t\tduplicate, longer, err := s.findContainedDuplicate(ctx, scope, item.Kind, content)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif duplicate != nil && !longer {\n\t\t\treturn duplicate, nil","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/memory/service.go#L334-L370","documentation":"Wraps a failure from repo.FindActiveByKey, which looks up an existing live memory item with the same normalized topic+content key before writing. The service needs to know whether the statement already exists to deduplicate or supersede it; if the storage lookup itself fails, the write is aborted with this message.","triggerScenarios":"Calling Remember, PromoteTopic, CreateItem, mergeRedundant, applyDecisions or observeTopics when the underlying memory repository (DB) errors on FindActiveByKey — e.g. DB connection failure, timeout, table missing, or context canceled mid-query.","commonSituations":"Database outage or connection pool exhaustion during a chat turn that extracts memories; context deadline exceeded when the memory write happens inside a request with a short timeout; schema drift after migration where the memory_items index/key lookup fails.","solutions":["Check the wrapped cause (%w) for the actual repo/DB error and fix that layer first (connectivity, migration, constraint).","Verify the memory repository backend is reachable and the schema/migrations for memory items are applied.","Increase the context timeout or run memory extraction outside the request path if deadline exceeded.","Retry the memory write; the operation is idempotent because existing items with identical content are returned as-is."],"exampleFix":"// before\nexisting, err := s.repo.FindActiveByKey(ctx, scope, normalizedKey)\nif err != nil {\n    return nil, fmt.Errorf(\"find conflicting memory: %w\", err)\n}\n// after\nexisting, err := s.repo.FindActiveByKey(ctx, scope, normalizedKey)\nif err != nil {\n    logger.Warnf(ctx, \"memory: find conflicting item failed: %v\", err)\n    return nil, fmt.Errorf(\"find conflicting memory: %w\", err) // keep wrap, but ensure caller retries\n}","handlingStrategy":"try-catch","validationCode":"// pre-check connectivity\nif err := s.repo.Ping(ctx); err != nil { return fmt.Errorf(\"memory repo unavailable: %w\", err) }","typeGuard":null,"tryCatchPattern":"existing, err := svc.Remember(ctx, scope, item)\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) { /* retry with longer timeout */ }\n    var dbErr *storage.DBError\n    if errors.As(err, &dbErr) { /* alert on repo health */ }\n    return fmt.Errorf(\"memory write skipped: %w\", err)\n}","preventionTips":["Monitor repo/DB health and alert on FindActiveByKey latency/errors","Apply DB migrations for memory tables before deploying","Run memory extraction with a context timeout generous enough for two DB round trips"],"tags":["database","memory","repository"],"backgroundTag":"memory-repo-lookup-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}