{"record":{"id":"ee5b3c9dd56a4ee6","repo":"thanos-io/thanos","slug":"write-new-meta","errorCode":null,"errorMessage":"write new meta","messagePattern":"write new meta","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/metadata/meta.go","lineNumber":191,"sourceCode":"\tResolution int64 `json:\"resolution\"`\n}\n\n// InjectThanos sets Thanos meta to the block meta JSON and saves it to the disk.\n// NOTE: It should be used after writing any block by any Thanos component, otherwise we will miss crucial metadata.\nfunc InjectThanos(logger log.Logger, bdir string, meta Thanos, downsampledMeta *tsdb.BlockMeta) (*Meta, error) {\n\tnewMeta, err := ReadFromDir(bdir)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"read new meta\")\n\t}\n\tnewMeta.Thanos = meta\n\n\t// While downsampling we need to copy original compaction.\n\tif downsampledMeta != nil {\n\t\tnewMeta.Compaction = downsampledMeta.Compaction\n\t}\n\n\tif err := newMeta.WriteToDir(logger, bdir); err != nil {\n\t\treturn nil, errors.Wrap(err, \"write new meta\")\n\t}\n\n\treturn newMeta, nil\n}\n\n// GroupKey returns a unique identifier for the compaction group the block belongs to.\n// It considers the downsampling resolution and the block's labels.\nfunc (m *Thanos) GroupKey() string {\n\treturn fmt.Sprintf(\"%d@%v\", m.Downsample.Resolution, labels.FromMap(m.Labels).Hash())\n}\n\n// ResolutionString returns a the block's resolution as a string.\nfunc (m *Thanos) ResolutionString() string {\n\treturn fmt.Sprintf(\"%d\", m.Downsample.Resolution)\n}\n\n// WriteToDir writes the encoded meta into <dir>/meta.json.\nfunc (m Meta) WriteToDir(logger log.Logger, dir string) error {","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/metadata/meta.go#L173-L209","documentation":"InjectThanos wraps the failure of newMeta.WriteToDir, which serializes the merged meta (with the Thanos section) back to meta.json on disk. It means the updated metadata could not be persisted, leaving the block without the Thanos metadata despite the in-memory value being correct.","triggerScenarios":"WriteToDir failing due to unwritable directory, permission denied, disk full, bdir being read-only, or filesystem I/O errors during the write/sync/rename.","commonSituations":"Running as a user without write permission on the block dir; disk full on the storage volume; block dir mounted read-only; antivirus/backup tooling locking meta.json during the write.","solutions":["Check filesystem permissions on bdir (needs write access, typically 0750/0755).","Verify free disk space and that the volume is not mounted read-only.","Retry the operation after resolving transient I/O errors; ensure no process holds meta.json locked.","If the block cannot be updated, re-create the block with the correct Thanos meta."],"exampleFix":"// before\n$ chmod 555 /data/store/01BK.../ && ./thanos inject-meta\n// after\n$ chmod 750 /data/store/01BK.../ && ./thanos inject-meta","handlingStrategy":"try-catch","validationCode":"if err := unix.Access(bdir, unix.W_OK); err != nil {\n    return fmt.Errorf(\"block dir %s not writable: %w\", bdir, err)\n}","typeGuard":null,"tryCatchPattern":"meta, err := InjectThanos(logger, bdir, thanosMeta, nil)\nif err != nil {\n    if strings.Contains(err.Error(), \"write new meta\") {\n        // check disk space / permissions, then retry once\n        return fmt.Errorf(\"persisting thanos meta failed: %w\", err)\n    }\n    return err\n}","preventionTips":["Run compaction/upload processes with write access to the block directories.","Monitor disk free space on the block store volume.","Avoid read-only mounts or AV/backup locks on meta.json during compaction."],"tags":["go","metadata","file-write-failed"],"backgroundTag":"file-write-failed","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}