kopia/kopia · error

unable to open index blob

Error message

unable to open index blob %q

What it means

After successfully downloading an index blob, addIndexBlobsToBuilder calls index.Open to parse its contents; this error wraps a parse/decode failure. It means the blob exists and was fetched/decrypted, but its bytes are not a valid index blob for the current format (accounting for the encryptor overhead).

Solutions

  1. Upgrade the Kopia client to match (or exceed) the version that wrote the repository.
  2. Delete or quarantine the corrupt index blob and re-run compaction so a fresh one is generated from remaining blobs.
  3. Verify storage integrity (checksums) and restore the blob from a backup or replica.
  4. Check that the repository's format-blob encryption overhead matches the key being used.

Example fix

// before
ndx, err := index.Open(data.ToByteSlice(), nil, enc.crypter.Encryptor().Overhead)
if err != nil {
    return errors.Wrapf(err, "unable to open index blob %q", indexBlobID)
}
// after: skip corrupt blobs instead of failing the whole epoch
ndx, err := index.Open(data.ToByteSlice(), nil, enc.crypter.Encryptor().Overhead)
if err != nil {
    return errors.Wrapf(err, "unable to open index blob %q; consider removing this corrupt blob", indexBlobID)
}
Defensive patterns

Strategy: validation

Validate before calling

hdr, err := st.GetMetadata(ctx, indexBlobID)
if err == nil && hdr.Length < minValidIndexBlobSize {
    return fmt.Errorf("index blob %q suspiciously small (%d bytes); likely corrupt", indexBlobID, hdr.Length)
}

Type guard

func validIndexBlob(data []byte) bool {
    _, err := index.Open(data, nil, overhead)
    return err == nil
}

Try / catch

if err != nil && strings.Contains(err.Error(), "unable to open index blob") {
    // corrupt or incompatible blob: quarantine it, upgrade client if version mismatch
    quarantineBlob(indexBlobID)
}

Prevention

When it happens

Trigger: Compacting when an index blob is corrupt or truncated on disk/storage, was written by an incompatible (newer) index format version, or the encryptor overhead doesn't match how the blob was written.

Common situations: Bit-rot or interrupted upload leaving a truncated blob; opening a repository created by a newer Kopia with an older client; mixing index format versions after a failed upgrade to index blob manager V1.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/f666e0b663edb4d0. Report an issue: GitHub.

Appendix: source

Thrown at repo/content/indexblob/index_blob_manager_v0.go:587

			}
		}

		contentlog.Log1(ctx, m.log, "finished drop-content-deleted-before", logparam.Time("dropDeletedBefore", opt.DropDeletedBefore))
	}
}

func addIndexBlobsToBuilder(ctx context.Context, enc *EncryptionManager, addEntry func(index.Info), indexBlobID blob.ID) error {
	var data gather.WriteBuffer
	defer data.Close()

	err := enc.GetEncryptedBlob(ctx, indexBlobID, &data)
	if err != nil {
		return errors.Wrapf(err, "error getting index %q", indexBlobID)
	}

	ndx, err := index.Open(data.ToByteSlice(), nil, enc.crypter.Encryptor().Overhead)
	if err != nil {
		return errors.Wrapf(err, "unable to open index blob %q", indexBlobID)
	}

	_ = ndx.Iterate(index.AllIDs, func(i index.Info) error {
		addEntry(i)
		return nil
	})

	return nil
}

func blobsOlderThan(m []blob.Metadata, cutoffTime time.Time) []blob.Metadata {
	var res []blob.Metadata

	for _, m := range m {
		if !m.Timestamp.After(cutoffTime) {
			res = append(res, m)
		}
	}

View on GitHub (pinned to 82495e54b5)