Tencent/WeKnora · error

storage directory not accessible

Error message

storage directory not accessible: %w

What it means

localFileService.CheckConnectivity wraps os.Stat errors on s.baseDir with "storage directory not accessible: %w". It runs during health/connectivity checks to verify local file storage is usable. The wrapped error is almost always "no such file or directory" (ENOSQL dir missing) or "permission denied".

Solutions

  1. Create the configured base directory: mkdir -p <LOCAL_STORAGE_BASE_DIR> (SaveFile creates subdirs, but the base itself must exist for connectivity checks).
  2. Check the storage config/LOCAL_FILE_BASE_DIR env var points to the intended absolute path, not a typo or a path removed in a newer image.
  3. Fix ownership/permissions so the service user can read/stat the directory (e.g. chown -R appuser:appuser /data/files, chmod 755).
  4. In containerized deployments, verify the volume mount exists and is mounted (docker inspect / kubectl describe pod) and the PVC is Bound.

Example fix

// before
// LOCAL_FILE_BASE_DIR=/data/weknora/files  (dir missing in container)
// after
// Dockerfile / entrypoint
RUN mkdir -p /data/weknora/files && chown -R appuser /data/weknora/files
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(baseDir)
if err != nil || !info.IsDir() {
	return fmt.Errorf("base dir %q unusable: %v", baseDir, err)
}

Try / catch

if err := svc.CheckConnectivity(ctx); err != nil {
	log.Fatalf("local storage unavailable: %v", err) // fail fast at boot
}

Prevention

When it happens

Trigger: os.Stat(baseDir) fails: the LOCAL_STORAGE_BASE_DIR directory doesn't exist, was deleted at runtime, is on an unmounted volume, or the process lacks read permission on it.

Common situations: Docker/K8s volume not mounted or mount path typo; fresh deployment where the data dir was never created; running container as non-root user while dir is root-owned; base dir on a detached PVC or host path that changed between restarts.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/a66fd35e52e873b5. Report an issue: GitHub.

Appendix: source

Thrown at internal/application/service/file/local.go:30

	"github.com/Tencent/WeKnora/internal/logger"
	"github.com/Tencent/WeKnora/internal/types/interfaces"
	secutils "github.com/Tencent/WeKnora/internal/utils"
)

// localFileService implements the FileService interface for local file system storage
type localFileService struct {
	baseDir     string // Base directory for file storage
	externalURL string // External URL base for presigned URL generation (empty = return local:// paths)
}

const localScheme = "local://"

// CheckConnectivity verifies the local storage directory exists and is accessible.
func (s *localFileService) CheckConnectivity(ctx context.Context) error {
	info, err := os.Stat(s.baseDir)
	if err != nil {
		return fmt.Errorf("storage directory not accessible: %w", err)
	}
	if !info.IsDir() {
		return fmt.Errorf("storage path is not a directory: %s", s.baseDir)
	}
	return nil
}

// NewLocalFileService creates a new local file service instance.
// externalURL is the externally-reachable base URL (e.g. "https://weknora.example.com");
// when set, GetFileURL returns presigned HTTP URLs instead of local:// paths.
func NewLocalFileService(baseDir, externalURL string) interfaces.FileService {
	return &localFileService{
		baseDir:     baseDir,
		externalURL: strings.TrimRight(externalURL, "/"),
	}
}

// SaveFile stores an uploaded file to the local file system

View on GitHub (pinned to 988cbb0330)