{"record":{"id":"1e817b292ef7e757","repo":"Tencent/WeKnora","slug":"failed-to-create-directory-w","errorCode":null,"errorMessage":"failed to create directory: %w","messagePattern":"failed to create directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/file/local.go","lineNumber":67,"sourceCode":"// The file is stored in a directory structure: baseDir/tenantID/knowledgeID/filename\n// Returns the full file path or an error if saving fails\nfunc (s *localFileService) SaveFile(ctx context.Context,\n\tfile *multipart.FileHeader, tenantID uint64, knowledgeID string,\n) (string, error) {\n\tlogger.Info(ctx, \"Starting to save file locally\")\n\tlogger.Infof(ctx, \"File information: name=%s, size=%d, tenant ID=%d, knowledge ID=%s\",\n\t\tfile.Filename, file.Size, tenantID, knowledgeID)\n\n\t// Create storage directory with tenant and knowledge ID\n\tdir := filepath.Join(s.baseDir, fmt.Sprintf(\"%d\", tenantID), knowledgeID)\n\tif _, err := secutils.SafePathUnderBase(s.baseDir, dir); err != nil {\n\t\tlogger.Errorf(ctx, \"Path traversal denied for SaveFile dir: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"invalid path: %w\", err)\n\t}\n\tlogger.Infof(ctx, \"Creating directory: %s\", dir)\n\tif err := os.MkdirAll(dir, 0o755); err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to create directory: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to create directory: %w\", err)\n\t}\n\n\t// Generate unique filename using timestamp\n\text := filepath.Ext(file.Filename)\n\tfilename := fmt.Sprintf(\"%d%s\", time.Now().UnixNano(), ext)\n\tfilePath := filepath.Join(dir, filename)\n\tlogger.Infof(ctx, \"Generated file path: %s\", filePath)\n\n\t// Open source file for reading\n\tlogger.Info(ctx, \"Opening source file\")\n\tsrc, err := file.Open()\n\tif err != nil {\n\t\tlogger.Errorf(ctx, \"Failed to open source file: %v\", err)\n\t\treturn \"\", fmt.Errorf(\"failed to open file: %w\", err)\n\t}\n\tdefer src.Close()\n\n\t// Create destination file for writing","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/file/local.go#L49-L85","documentation":"localFileService.SaveFile wraps os.MkdirAll errors with \"failed to create directory: %w\". The directory path passed traversal validation but the OS refused to create baseDir/tenantID/knowledgeID — typically permission denied, a file occupying the path, read-only filesystem, or disk/exhausted-inode conditions.","triggerScenarios":"os.MkdirAll fails with EACCES (service user can't write under baseDir), ENOTDIR (a component like baseDir/tenantID exists as a file), EROFS (read-only mount), or ENOSPC.","commonSituations":"Container runs as non-root while baseDir is root-owned; PVC mounted read-only; a file named like a tenant ID exists (e.g. created by touch or collision); disk full after large uploads; SELinux/AppArmor blocking writes.","solutions":["Check the wrapped errno: EACCES → chown/chmod baseDir so the service user has write access (chown -R appuser baseDir; chmod u+w).","ENOTDIR → remove or rename the file that occupies the tenant/knowledge path component.","EROFS → remount the volume read-write or point baseDir at a writable volume.","ENOSPC → free disk space or expand the volume; monitor disk usage for the storage mount.","Verify the path passes validation but is sane on disk: ls -la baseDir/tenantID to spot conflicting entries."],"exampleFix":"// before\n// container user uid=1000, baseDir owned by root:root 755 → MkdirAll EACCES\n// after\n// deploy.yaml\nsecurityContext: { runAsUser: 1000 }\n// plus initContainer: chown -R 1000:1000 /data/weknora/files","handlingStrategy":"try-catch","validationCode":"// pre-flight writability check\ntest := filepath.Join(baseDir, \".write-test\")\nif err := os.WriteFile(test, nil, 0o644); err != nil { /* storage not writable */ }\nos.Remove(test)","typeGuard":null,"tryCatchPattern":"if _, err := svc.SaveFile(ctx, fh, tenantID, knowledgeID); err != nil {\n\tif strings.Contains(err.Error(), \"failed to create directory\") {\n\t\t// check errno: EACCES→permissions, EROFS→mount, ENOSPC→disk\n\t\treturn StorageUnavailable\n\t}\n\treturn err\n}","preventionTips":["Chown the storage tree to the service user at deploy time","Mount storage volumes read-write and monitor free space","Add a writability probe to startup/readiness checks","Keep tenant/knowledge directory components collision-free (use generated IDs)"],"tags":["filesystem","permissions","local-storage","deployment","go"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}