{"record":{"id":"2a370c7ef1ca7ce5","repo":"vxcontrol/pentagi","slug":"w-resource-q-already-exists-and-is-not-a-direct","errorCode":null,"errorMessage":"%w: resource %q already exists and is not a directory","messagePattern":"%w: resource %q already exists and is not a directory","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/pkg/server/services/resources.go","lineNumber":2099,"sourceCode":"\t\treturn nil, nil, nil, nil\n\t}\n\n\tparts := strings.Split(dirPath, \"/\")\n\tcreated := make([]models.UserResource, 0, len(parts))\n\tdeleted := make([]models.UserResource, 0, len(parts))\n\torphanHashes := make([]string, 0, len(parts))\n\tcurrent := \"\"\n\tfor _, part := range parts {\n\t\tcurrent = resources.FilePath(current, part)\n\n\t\texisting, exists, err := findResourceByPath(tx, uid, current)\n\t\tif err != nil {\n\t\t\treturn nil, nil, nil, err\n\t\t}\n\t\tif exists {\n\t\t\tif !existing.IsDir {\n\t\t\t\tif !force {\n\t\t\t\t\treturn nil, nil, nil, fmt.Errorf(\"%w: resource %q already exists and is not a directory\", errResourceConflict, current)\n\t\t\t\t}\n\t\t\t\tif err := tx.Delete(&existing).Error; err != nil {\n\t\t\t\t\treturn nil, nil, nil, fmt.Errorf(\"failed to delete file blocking directory %q: %w\", current, err)\n\t\t\t\t}\n\t\t\t\tdeleted = append(deleted, existing)\n\t\t\t\tif existing.Hash != \"\" {\n\t\t\t\t\torphanHashes = append(orphanHashes, existing.Hash)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\trec := models.UserResource{\n\t\t\tUserID: uid,\n\t\t\tHash:   \"\",\n\t\t\tName:   path.Base(current),\n\t\t\tPath:   current,","sourceCodeStart":2081,"sourceCodeEnd":2117,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/services/resources.go#L2081-L2117","documentation":"ensureResourceDirs builds every missing parent directory row for a target path. If an intermediate path component already exists as a FILE (IsDir=false), a directory cannot be created there: without force it returns errResourceConflict wrapped as 'already exists and is not a directory'; with force it deletes the blocking file instead.","triggerScenarios":"Uploading/moving/copying to path a/b/c when a or a/b is registered as a file, e.g. after a previous upload named 'a' as a file; also hit when path segments collide with an uploaded file's name.","commonSituations":"Uploading a file named 'data' then later uploading to data/file.txt; directory layouts changed between API versions; scripts creating flat file names that later collide with folder paths.","solutions":["Delete or rename the existing file that occupies the directory path, or pass force=true to auto-delete it","Pick a different target path that does not traverse an existing file","List resources to find the offending file at one of the parent segments before uploading"],"exampleFix":"// before\nupload(\"reports/2024/q1.csv\") // 'reports' exists as a file → conflict\n// after\nupload(\"reports/2024/q1.csv?force=true\") // deletes blocking file, or:\ndeleteResource(\"reports\"); upload(\"reports/2024/q1.csv\")","handlingStrategy":"validation","validationCode":"// check every parent segment before upload/move/copy\nsegs := strings.Split(strings.Trim(target, \"/\"), \"/\")\ncur := \"\"\nfor _, s := range segs {\n    cur += \"/\" + s\n    if e, ok := lookup(uid, cur); ok && !e.IsDir {\n        return fmt.Errorf(\"%s is a file; delete it or use force\", cur)\n    }\n}","typeGuard":"func pathClearForDir(entries []Resource, dir string) bool {\n    for _, e := range entries {\n        if (e.Path == dir || strings.HasPrefix(dir, e.Path+\"/\")) && !e.IsDir {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"if err := upload(target, r); err != nil {\n    if errors.Is(err, errResourceConflict) {\n        return fmt.Errorf(\"a file blocks a directory component of %s; delete it or retry with force\", target)\n    }\n    return err\n}","preventionTips":["Before uploading into new subfolders, confirm no parent segment exists as a file","Avoid file names that could later be used as folder names in the same tree","Use force=true only when deleting the blocking file is acceptable","Normalize/validate path segments client-side (no empty or colliding segments)"],"tags":["conflict","validation","paths","resources"],"backgroundTag":"path-is-a-file","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}