thanos-io/thanos · error
open data dir
Error message
open data dir
What it means
When sidecar upload is enabled, runRule opens the rule evaluator's data directory with os.OpenRoot(conf.dataDir) to hand it to the shipper. If the directory cannot be opened (missing, not a directory, permission denied), the error is wrapped as "open data dir" and startup aborts.
Solutions
- Ensure --data-dir exists and is a writable directory (mkdir -p and chown to the process user).
- Mount a persistent volume at the dataDir path in your container spec.
- Fix the --data-dir flag value if it points to a file or a typo'd path.
- Remove the read-only flag from the volume mount, or disable shipping if upload is not intended.
Example fix
// before thanos rule --data-dir=/mnt/missing/rule --objstore-bucket=thanos // after mkdir -p /var/thanos/rule && thanos rule --data-dir=/var/thanos/rule --objstore-bucket=thanos
Defensive patterns
Strategy: validation
Validate before calling
test -d "$DATA_DIR" || mkdir -p "$DATA_DIR"; test -w "$DATA_DIR" || { echo "data dir not writable"; exit 1; } Prevention
- Mount a writable volume at --data-dir when shipping is enabled
- Create the directory in an init container
- Double-check flag values for typos
When it happens
Trigger: Running thanos rule with --objstore-bucket (shipper enabled) where --data-dir does not exist and cannot be created/opened, points to a file, or the process lacks read permission on it.
Common situations: Forgetting to mount the persistent volume that holds --data-dir in Kubernetes; dataDir typo like /var/thanos/ruel; volume mounted read-only while the shipper needs write access.
Related errors
- get content of relabel configuration
- create meta fetcher
- create syncer
- create working compact directory
- create working downsample directory
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/9dec502e859ec2d4.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/thanos/rule.go:901
}
confContentYaml, err := conf.objStoreConfig.Content()
if err != nil {
return err
}
if len(confContentYaml) > 0 {
// The background shipper continuously scans the data directory and uploads
// new blocks to Google Cloud Storage or an S3-compatible storage service.
bkt, err := client.NewBucket(logger, confContentYaml, component.Rule.String(), nil)
if err != nil {
return err
}
bkt = objstoretracing.WrapWithTraces(objstore.WrapWithMetrics(bkt, extprom.WrapRegistererWithPrefix("thanos_", reg), bkt.Name()))
dataDir, err := os.OpenRoot(conf.dataDir)
if err != nil {
return errors.Wrap(err, "open data dir")
}
s := shipper.New(
bkt,
dataDir,
shipper.WithLogger(logger),
shipper.WithRegisterer(reg),
shipper.WithSource(metadata.RulerSource),
shipper.WithHashFunc(metadata.HashFunc(conf.shipper.hashFunc)),
shipper.WithMetaFileName(conf.shipper.metaFileName),
shipper.WithLabels(func() labels.Labels { return conf.lset }),
shipper.WithAllowOutOfOrderUploads(conf.shipper.allowOutOfOrderUpload),
shipper.WithSkipCorruptedBlocks(conf.shipper.skipCorruptedBlocks),
shipper.WithUploadConcurrency(conf.shipper.uploadConcurrency),
)
ctx, cancel := context.WithCancel(context.Background())
View on GitHub (pinned to 35b8b99117)