{"record":{"id":"af3fdcc8de036fe6","repo":"Tencent/WeKnora","slug":"create-wiki-folder-w","errorCode":null,"errorMessage":"create wiki folder: %w","messagePattern":"create wiki folder: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/wiki_page.go","lineNumber":1542,"sourceCode":"\n\tpath := name\n\tif parentPath != \"\" {\n\t\tpath = parentPath + \"/\" + name\n\t}\n\tnow := time.Now()\n\tfolder := &types.WikiFolder{\n\t\tID:              uuid.New().String(),\n\t\tTenantID:        tenantID,\n\t\tKnowledgeBaseID: kbID,\n\t\tParentID:        parentID,\n\t\tName:            name,\n\t\tPath:            path,\n\t\tDepth:           depth,\n\t\tCreatedAt:       now,\n\t\tUpdatedAt:       now,\n\t}\n\tif err := s.repo.CreateFolder(ctx, folder); err != nil {\n\t\treturn nil, fmt.Errorf(\"create wiki folder: %w\", err)\n\t}\n\treturn folder, nil\n}\n\n// FindOrCreateFolderPath resolves a category path to a leaf folder id, creating\n// any missing intermediate folders along the way. Concurrency-safe against the\n// unique (kb, parent, name) constraint via a re-fetch on create conflict.\nfunc (s *wikiPageService) FindOrCreateFolderPath(\n\tctx context.Context, kbID string, tenantID uint64, path []string,\n) (string, []string, error) {\n\tclean := types.CleanWikiCategoryPath(path)\n\tif len(clean) == 0 {\n\t\treturn types.WikiFolderRootID, nil, nil\n\t}\n\tparentID := types.WikiFolderRootID\n\tparentPath := \"\"\n\tfor depth, name := range clean {\n\t\tchild, err := s.repo.GetChildFolderByName(ctx, kbID, parentID, name)","sourceCodeStart":1524,"sourceCodeEnd":1560,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/wiki_page.go#L1524-L1560","documentation":"CreateFolder builds the folder entity and persists it via repo.CreateFolder; storage failure is wrapped as 'create wiki folder: %w'. The name has already passed validateFolderName, so failures here are persistence-level: DB errors or path uniqueness conflicts.","triggerScenarios":"CreateFolder where repo.CreateFolder fails — duplicate folder path/name in the same parent, DB connectivity loss, context canceled, or constraint violation on path/depth columns.","commonSituations":"Two users creating identically named folders in the same parent concurrently (unique path constraint); DB outages during folder-tree imports; schema drift on the folders table after migrations.","solutions":["Check the wrapped cause: for duplicate-path errors, reuse the existing folder (or use FindOrCreateFolderPath, which is documented as concurrency-safe).","Retry transient DB failures with backoff.","Verify folders-table migrations and unique constraints are current.","Serialize folder creation per parent in client workflows that bulk-import trees."],"exampleFix":"// before\nfolder, err := svc.CreateFolder(ctx, kbID, parentID, \"Reports\")\nif err != nil { return err } // fails on concurrent duplicate\n// after\nfolderID, err := svc.FindOrCreateFolderPath(ctx, kbID, []string{\"Reports\"})\nif err != nil { return err } // concurrency-safe","handlingStrategy":"fallback","validationCode":"name, err := sanitizeFolderName(requestedName) // strips/rejects separators up front\nif err != nil { return err }","typeGuard":null,"tryCatchPattern":"folder, err := svc.CreateFolder(ctx, kbID, parentID, name)\nif err != nil && strings.Contains(err.Error(), \"create wiki folder:\") {\n    if isDuplicatePath(err) {\n        folderID, err = svc.FindOrCreateFolderPath(ctx, kbID, []string{name})\n    } else if isTransient(err) {\n        time.Sleep(backoff)\n        folder, err = svc.CreateFolder(ctx, kbID, parentID, name)\n    }\n}","preventionTips":["Use concurrency-safe FindOrCreateFolderPath for bulk or racy folder creation","Handle duplicate-path errors by reusing the existing folder","Keep folders-table migrations and unique path constraints current","Retry transient DB failures with exponential backoff"],"tags":["database","folder","wrapped-error"],"backgroundTag":"database-insert-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}