{"record":{"id":"3df7f10d8040aa6a","repo":"thanos-io/thanos","slug":"invalid-magic-number-x-for-s","errorCode":null,"errorMessage":"invalid magic number %x for %s","messagePattern":"invalid magic number %x for (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/block/indexheader/binary_reader.go","lineNumber":204,"sourceCode":"\t}\n\n\trc, err := bkt.GetRange(ctx, indexFilepath, 0, index.HeaderLen)\n\tif err != nil {\n\t\treturn nil, 0, errors.Wrapf(err, \"get TOC from object storage of %s\", indexFilepath)\n\t}\n\n\tb, err := io.ReadAll(rc)\n\tif err != nil {\n\t\trunutil.CloseWithErrCapture(&err, rc, \"close reader\")\n\t\treturn nil, 0, errors.Wrapf(err, \"get header from object storage of %s\", indexFilepath)\n\t}\n\n\tif err := rc.Close(); err != nil {\n\t\treturn nil, 0, errors.Wrap(err, \"close reader\")\n\t}\n\n\tif m := binary.BigEndian.Uint32(b[0:4]); m != index.MagicIndex {\n\t\treturn nil, 0, errors.Errorf(\"invalid magic number %x for %s\", m, indexFilepath)\n\t}\n\n\tversion := int(b[4:5][0])\n\n\tif version != index.FormatV1 && version != index.FormatV2 {\n\t\treturn nil, 0, errors.Errorf(\"not supported index file version %d of %s\", version, indexFilepath)\n\t}\n\n\tir := &chunkedIndexReader{\n\t\tctx:  ctx,\n\t\tpath: indexFilepath,\n\t\tsize: uint64(attrs.Size),\n\t\tbkt:  bkt,\n\t}\n\n\ttoc, err := ir.readTOC()\n\tif err != nil {\n\t\treturn nil, 0, err","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/indexheader/binary_reader.go#L186-L222","documentation":"When Thanos builds a binary index-header for a TSDB block, it reads the first 4 bytes of the block's index file from object storage and expects the Prometheus index magic number 0xBAAAD792 (index.MagicIndex). If the bytes differ, the file is not a valid TSDB index (or is truncated/corrupted), so newChunkedIndexReader aborts instead of parsing garbage. The message names the magic actually found and the index file path.","triggerScenarios":"Writing a binary index-header (WriteBinary -> newChunkedIndexReader) against a block whose index file in the bucket is missing, truncated (fewer than 4 readable bytes yield a wrong value), a placeholder/zero object, or simply not a Prometheus TSDB index file (e.g. wrong object uploaded to the block's index path).","commonSituations":"Partial multi-part uploads or failed sync leaving a truncated index object; pointing the bucket at a path containing meta.json or chunks instead of index; manually uploaded or transformed blocks; object storage returning zero-filled bodies on some errors; blocks written by forks/tools that do not use the Prometheus index format.","solutions":["Verify the object at the reported indexFilepath is a real Prometheus index: first 4 bytes should be ba aa d7 92 (big-endian); download the first bytes and inspect.","Re-upload or re-sync the block from a healthy source (e.g. re-run thanos block sync / re-upload from compactor) to replace the truncated or wrong object.","Check the block directory layout: the index must be at <block-id>/index with the block's meta.json alongside; fix bucket/prefix configuration if paths are shifted.","If a tool rewrote the index, confirm it emits the standard Prometheus index format matching FormatV1/V2 expected by this Thanos version.","Rule out object-storage proxies/CDNs returning empty or error bodies with 200; fetch the object directly from the storage backend."],"exampleFix":"// before: blindly building index-header for a possibly corrupt block\nr, _, err := newChunkedIndexReader(ctx, bkt, indexFilepath, attrs, b)\n// after: pre-validate the magic before building the reader\nrc, _ := bkt.GetRange(ctx, indexFilepath, 0, 4)\nb0, _ := io.ReadAll(rc)\nif binary.BigEndian.Uint32(b0) != index.MagicIndex {\n    return nil, fmt.Errorf(\"block %s has corrupt index, re-upload\", indexFilepath)\n}\nr, _, err := newChunkedIndexReader(ctx, bkt, indexFilepath, attrs, b)","handlingStrategy":"validation","validationCode":"func validateIndexMagic(ctx context.Context, bkt objstore.BucketReader, path string) error {\n    rc, err := bkt.GetRange(ctx, path, 0, 4)\n    if err != nil { return err }\n    defer rc.Close()\n    b, err := io.ReadAll(rc)\n    if err != nil { return err }\n    if binary.BigEndian.Uint32(b) != index.MagicIndex {\n        return fmt.Errorf(\"%s is not a TSDB index (bad magic)\", path)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Before onboarding blocks, verify each index object starts with magic 0xBAAAD792.","Use thanos tools bucket verify periodically to catch corrupt/truncated blocks early.","Ensure uploads of block directories are atomic and complete (upload index last or verify after upload).","Never point Thanos at buckets written by non-Prometheus index formats."],"tags":["object-storage","corruption","index-header","thanos","validation"],"backgroundTag":"file-not-found","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"}