Tencent/WeKnora · error
failed to create directory: %w
Error message
failed to create directory: %w
What it means
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.
Source
Thrown at internal/application/service/file/local.go:67
// The file is stored in a directory structure: baseDir/tenantID/knowledgeID/filename
// Returns the full file path or an error if saving fails
func (s *localFileService) SaveFile(ctx context.Context,
file *multipart.FileHeader, tenantID uint64, knowledgeID string,
) (string, error) {
logger.Info(ctx, "Starting to save file locally")
logger.Infof(ctx, "File information: name=%s, size=%d, tenant ID=%d, knowledge ID=%s",
file.Filename, file.Size, tenantID, knowledgeID)
// Create storage directory with tenant and knowledge ID
dir := filepath.Join(s.baseDir, fmt.Sprintf("%d", tenantID), knowledgeID)
if _, err := secutils.SafePathUnderBase(s.baseDir, dir); err != nil {
logger.Errorf(ctx, "Path traversal denied for SaveFile dir: %v", err)
return "", fmt.Errorf("invalid path: %w", err)
}
logger.Infof(ctx, "Creating directory: %s", dir)
if err := os.MkdirAll(dir, 0o755); err != nil {
logger.Errorf(ctx, "Failed to create directory: %v", err)
return "", fmt.Errorf("failed to create directory: %w", err)
}
// Generate unique filename using timestamp
ext := filepath.Ext(file.Filename)
filename := fmt.Sprintf("%d%s", time.Now().UnixNano(), ext)
filePath := filepath.Join(dir, filename)
logger.Infof(ctx, "Generated file path: %s", filePath)
// Open source file for reading
logger.Info(ctx, "Opening source file")
src, err := file.Open()
if err != nil {
logger.Errorf(ctx, "Failed to open source file: %v", err)
return "", fmt.Errorf("failed to open file: %w", err)
}
defer src.Close()
// Create destination file for writingView on GitHub (pinned to 988cbb0330)
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.
Example fix
// before
// container user uid=1000, baseDir owned by root:root 755 → MkdirAll EACCES
// after
// deploy.yaml
securityContext: { runAsUser: 1000 }
// plus initContainer: chown -R 1000:1000 /data/weknora/files Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight writability check
test := filepath.Join(baseDir, ".write-test")
if err := os.WriteFile(test, nil, 0o644); err != nil { /* storage not writable */ }
os.Remove(test) Try / catch
if _, err := svc.SaveFile(ctx, fh, tenantID, knowledgeID); err != nil {
if strings.Contains(err.Error(), "failed to create directory") {
// check errno: EACCES→permissions, EROFS→mount, ENOSPC→disk
return StorageUnavailable
}
return err
} Prevention
- 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)
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- storage directory not accessible: %w
- storage path is not a directory: %s
- failed to create file: %w
- failed to load script: %w
- failed to delete file from KS3: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/1e817b292ef7e757.
Report an issue: GitHub.