{"record":{"id":"d6fb70aa9c7e4aac","repo":"Tencent/WeKnora","slug":"w-slug-s-belongs-to-s","errorCode":null,"errorMessage":"%w: slug %s belongs to %s","messagePattern":"%w: slug (.+?) belongs to (.+?)","errorType":"exception","errorClass":"errWikiPageAmbiguous","httpStatus":null,"severity":"error","filePath":"internal/agent/tools/wiki_route_resolver.go","lineNumber":167,"sourceCode":"\t\t\t\t\"wiki page %s returned knowledge base %s while resolving allowed scope %s\",\n\t\t\t\tslug, page.KnowledgeBaseID, scope.KnowledgeBaseID,\n\t\t\t)\n\t\t}\n\t\tkbID := scope.KnowledgeBaseID\n\t\thits = append(hits, hit{page: page, kbID: kbID})\n\t\troutes.rememberPage(page, kbID)\n\t}\n\tswitch len(hits) {\n\tcase 0:\n\t\treturn nil, \"\", fmt.Errorf(\"%w: %s\", errWikiPageNotFoundInScope, slug)\n\tcase 1:\n\t\treturn hits[0].page, hits[0].kbID, nil\n\tdefault:\n\t\towners := make([]string, 0, len(hits))\n\t\tfor _, item := range hits {\n\t\t\towners = append(owners, item.kbID)\n\t\t}\n\t\treturn nil, \"\", fmt.Errorf(\"%w: slug %s belongs to %s\", errWikiPageAmbiguous, slug, strings.Join(owners, \", \"))\n\t}\n}\n\n// resolveWikiCreateKB selects a creation target only when server-side context\n// is unambiguous: one cached provenance owner or one Wiki KB in scope.\nfunc resolveWikiCreateKB(\n\tslug string,\n\tkbIDs []string,\n\troutes *WikiRouteResolver,\n\tserverHints ...string,\n) (string, error) {\n\tscopes := NewWikiScopesFromKBIDs(kbIDs)\n\tpreferred := routes.scopesForSlug(strings.TrimSpace(slug), scopes)\n\tallowed := make(map[string]struct{}, len(scopes))\n\tfor _, scope := range scopes {\n\t\tallowed[scope.KnowledgeBaseID] = struct{}{}\n\t}\n\tcandidates := make([]string, 0, len(preferred)+len(serverHints))","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/agent/tools/wiki_route_resolver.go#L149-L185","documentation":"When the same slug resolves to pages in two or more allowed knowledge bases, the resolver cannot pick a unique target and returns errWikiPageAmbiguous wrapped with the slug and the comma-joined list of owning KB IDs. This prevents mutating or reading the wrong page when a slug is duplicated across scopes.","triggerScenarios":"resolveUniqueWikiPage found len(hits) >= 2: GetPageBySlug succeeded for the same slug in multiple KBs within the allowed scopes (e.g. update/delete calls where no specific KB was pinned).","commonSituations":"Teams copying pages across knowledge bases keeping identical slugs; template pages replicated per project KB; overly broad KB scope list including several spaces that all define the slug.","solutions":["Narrow the allowed KB scopes so only one contains the slug, or pass the specific KB ID with the request","Rename one of the duplicate pages so slugs are unique across KBs","Prompt the model/user to disambiguate by listing the owning KBs from the error message","Use resolveWikiCreateKB-style provenance (cached owner) for follow-up operations on the same page"],"exampleFix":"// before: ambiguous scope\nkbIDs := allKBs\npage, _, err := resolveUniqueWikiPage(ctx, \"onboarding\", kbIDs, routes)\n// after: pin the KB\nkbIDs := []string{\"kb-team-platform\"}\npage, _, err := resolveUniqueWikiPage(ctx, \"onboarding\", kbIDs, routes)","handlingStrategy":"fallback","validationCode":"owners := kbIDsContainingSlug(ctx, slug, allowedKBs) // pre-check with list/search\nif len(owners) > 1 {\n    return fmt.Errorf(\"slug %q exists in KBs %v; pick one\", slug, owners)\n}","typeGuard":"null","tryCatchPattern":"page, kbID, err := resolveUniqueWikiPage(ctx, slug, kbIDs, routes)\nif err != nil && errors.Is(err, errWikiPageAmbiguous) {\n    // surface the KB list from err to the user and retry with a single KB scope\n}","preventionTips":["Enforce slug uniqueness across knowledge bases at creation time","Pass an explicit KB ID when scopes contain multiple KBs","Keep agent scopes narrow to a single writable KB when possible","Parse the owner list from the error to drive a disambiguation prompt"],"tags":["go","wiki","ambiguity","slug-conflict"],"backgroundTag":"ambiguous-slug","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}