{"record":{"id":"e6787b384f417feb","repo":"thanos-io/thanos","slug":"open-chunk-writer","errorCode":null,"errorMessage":"open chunk writer","messagePattern":"open chunk writer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/index.go","lineNumber":454,"sourceCode":"\tdefer runutil.CloseWithErrCapture(&err, b, \"repair block reader\")\n\n\tindexr, err := b.Index()\n\tif err != nil {\n\t\treturn resid, errors.Wrap(err, \"open index\")\n\t}\n\tdefer runutil.CloseWithErrCapture(&err, indexr, \"repair index reader\")\n\n\tchunkr, err := b.Chunks()\n\tif err != nil {\n\t\treturn resid, errors.Wrap(err, \"open chunks\")\n\t}\n\tdefer runutil.CloseWithErrCapture(&err, chunkr, \"repair chunk reader\")\n\n\tresdir := filepath.Join(dir, resid.String())\n\n\tchunkw, err := chunks.NewWriter(filepath.Join(resdir, ChunksDirname))\n\tif err != nil {\n\t\treturn resid, errors.Wrap(err, \"open chunk writer\")\n\t}\n\tdefer runutil.CloseWithErrCapture(&err, chunkw, \"repair chunk writer\")\n\n\tindexw, err := index.NewWriter(context.TODO(), filepath.Join(resdir, IndexFilename))\n\tif err != nil {\n\t\treturn resid, errors.Wrap(err, \"open index writer\")\n\t}\n\tdefer runutil.CloseWithErrCapture(&err, indexw, \"repair index writer\")\n\n\t// TODO(fabxc): adapt so we properly handle the version once we update to an upstream\n\t// that has multiple.\n\tresmeta := *meta\n\tresmeta.ULID = resid\n\tresmeta.Stats = tsdb.BlockStats{} // Reset stats.\n\tresmeta.Thanos.Source = source    // Update source.\n\n\tif err := rewrite(ctx, logger, indexr, chunkr, indexw, chunkw, &resmeta, ignoreChkFns); err != nil {\n\t\treturn resid, errors.Wrap(err, \"rewrite block\")","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/index.go#L436-L472","documentation":"block.Repair wraps the error from chunks.NewWriter, which creates the chunk writer for the new block directory chunks/<resid>/chunks/. Failure is almost always an OS-level problem creating the destination directory/files — missing parent dir, permission denied, or ENOSPC — not data corruption. Wrapped as 'open chunk writer: <cause>'.","triggerScenarios":"Repair on a dir where the new block's parent directory cannot be created (dir doesn't exist or is read-only); filesystem full; path too long; stale partial resdir from a previous failed repair run conflicting with permissions.","commonSituations":"Running repair against an object-storage-mounted (read-only FUSE) path; container running with a read-only rootfs or non-writable workdir; disk full during a large repair; repairing into a dir owned by a different user than the repair process.","solutions":["Ensure the target dir exists and is writable by the process running Repair (mkdir -p and chown/chmod as needed).","Free disk space if the wrapped error is ENOSPC.","Remove leftover partial result directories from earlier failed repairs before retrying.","Copy blocks to a local writable scratch dir, repair there, then upload the result instead of repairing in place on read-only mounts."],"exampleFix":"// before\nif _, err := block.Repair(ctx, logger, os.Getenv(\"MOUNT\"), id, source, fn) { ... } // MOUNT may be read-only\n// after\nworkdir := \"/var/tmp/thanos-repair\"\nif err := os.MkdirAll(workdir, 0o750); err != nil {\n    return err\n}\nif err := copyBlock(filepath.Join(workdir, id.String()), dir, id); err != nil {\n    return err\n}\nif _, err := block.Repair(ctx, logger, workdir, id, source, fn); err != nil {\n    return err\n}","handlingStrategy":"try-catch","validationCode":"if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {\n    return fmt.Errorf(\"repair target dir %s unavailable\", dir)\n}\ntest := filepath.Join(dir, \".repair-write-test\")\nif err := os.WriteFile(test, []byte(\"ok\"), 0o600); err != nil {\n    return fmt.Errorf(\"dir %s not writable: %w\", dir, err)\n}\nos.Remove(test)","typeGuard":null,"tryCatchPattern":"resid, err := block.RepairIssue347(ctx, logger, dir, id, source)\nif err != nil && strings.Contains(err.Error(), \"open chunk writer\") {\n    return resid, fmt.Errorf(\"cannot write repaired block into %s: %w (check permissions/free space)\", dir, err)\n}","preventionTips":["Run repair on local writable scratch storage, never on read-only or FUSE-mounted paths.","Pre-create the repair dir with correct ownership and adequate free space.","Clean up partial result directories from failed repair runs before retrying.","Check available disk space against the source block size before starting."],"tags":["thanos","filesystem","permissions","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"}