thanos-io/thanos · error

create dir

Error message

create dir

What it means

Returned by NewBucketStore when os.MkdirAll(dir, 0750) fails while creating the local block cache directory. The error is wrapped as "create dir: <cause>", so the cause is typically a permission problem, a read-only filesystem, or a path whose parent is a file.

Solutions

  1. Check that the parent of dir exists and is writable by the process user (ls -ld, id).
  2. Ensure the directory path does not collide with an existing file; fix the path or remove the file.
  3. In Kubernetes, mount an emptyDir/PVC at the store data directory and disable read-only root filesystem.
  4. Verify free disk space and filesystem mount options (ro vs rw).

Example fix

// before
dir := "/var/thanos/store" // may not exist or not be writable
// after
dir := "/var/thanos/store"
if err := os.MkdirAll(dir, 0750); err != nil {
    return errors.Wrapf(err, "cannot create store dir %s (check permissions/volume mounts)", dir)
}
Defensive patterns

Strategy: validation

Validate before calling

func ensureDirWritable(dir string) error {
    if err := os.MkdirAll(dir, 0750); err != nil { return err }
    probe := filepath.Join(dir, ".probe")
    if err := os.WriteFile(probe, []byte("ok"), 0600); err != nil { return err }
    return os.Remove(probe)
}

Prevention

When it happens

Trigger: NewBucketStore called with a data directory that cannot be created: parent directory not writable, path component exists as a regular file, disk full, or container running as non-root without volume permissions.

Common situations: Kubernetes pods with readOnlyRootFilesystem and no emptyDir mounted at the store dir, wrong ownership on a hostPath volume, or a typo making the dir path collide with an existing file.

Understand the failure class

Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/83ad458ec73ef4d4. Report an issue: GitHub.

Appendix: source

Thrown at pkg/store/bucket.go:700

	for _, option := range options {
		option(s)
	}

	// Depend on the options
	indexReaderPoolMetrics := indexheader.NewReaderPoolMetrics(extprom.WrapRegistererWithPrefix("thanos_bucket_store_", s.reg))
	s.indexReaderPool = indexheader.NewReaderPool(s.logger, lazyIndexReaderEnabled, lazyIndexReaderIdleTimeout, indexReaderPoolMetrics, s.indexHeaderLazyDownloadStrategy)
	s.metrics = newBucketStoreMetrics(s.reg) // TODO(metalmatze): Might be possible via Option too

	if err := s.validate(); err != nil {
		return nil, errors.Wrap(err, "validate config")
	}

	if dir == "" {
		return s, nil
	}

	if err := os.MkdirAll(dir, 0750); err != nil {
		return nil, errors.Wrap(err, "create dir")
	}

	return s, nil
}

// Close the store.
func (s *BucketStore) Close() (err error) {
	s.mtx.Lock()
	defer s.mtx.Unlock()

	for _, b := range s.blocks {
		runutil.CloseWithErrCapture(&err, b, "closing Bucket Block")
	}

	s.indexReaderPool.Close()
	return err
}

View on GitHub (pinned to 35b8b99117)