weaviate/weaviate · error

bucket '%s' must be in %s mode to be renamed

Error message

bucket '%s' must be in %s mode to be renamed

What it means

RenameBucket only permits renaming buckets that are in read-only mode (currBucket.isReadOnly() == false -> error). This prevents renaming a bucket that may still accept writes, which would break the invariant that writes land in the registered bucket name. The bucket must be flipped to storagestate.StatusReadOnly first.

Source

Thrown at adapters/repos/db/lsmkv/store.go:677

	if s.closed {
		return fmt.Errorf("%w: renaming bucket %q for %q in store %q", ErrAlreadyClosed, bucketName, newBucketName, s.dir)
	}

	s.bucketAccessLock.Lock()
	defer s.bucketAccessLock.Unlock()

	currBucket := s.bucketsByName[bucketName]
	if currBucket == nil {
		return fmt.Errorf("bucket '%s' not found", bucketName)
	}
	newBucket := s.bucketsByName[newBucketName]
	if newBucket != nil {
		return fmt.Errorf("bucket '%s' already exists", newBucketName)
	}

	if !currBucket.isReadOnly() {
		return fmt.Errorf("bucket '%s' must be in %s mode to be renamed", bucketName, storagestate.StatusReadOnly)
	}

	currBucketDir := currBucket.dir
	newBucketDir := s.bucketDir(newBucketName)

	currBucket.flushLock.Lock()
	defer currBucket.flushLock.Unlock()

	if currBucket.flushing != nil {
		return fmt.Errorf("bucket '%s' can not be renamed before flushing", bucketName)
	}

	currBucket.dir = newBucketDir

	mt, err := currBucket.createNewActiveMemtable()
	if err != nil {
		return fmt.Errorf("switch active memtable: %w", err)
	}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Put the bucket into read-only mode before renaming (the shard/schema layer sets this, e.g. via shard.SetReadOnly / stop writes)
  2. Quiesce all writes to the bucket, then confirm its status is read-only, then rename
  3. If the bucket should never be writable, verify how it was created — a writable bucket requires the full read-only transition

Example fix

// before
err := store.RenameBucket(ctx, oldName, newName)
// after
bucket := store.Bucket(oldName)
if !bucket.IsReadOnly() {
    if err := bucket.SetReadOnly(); err != nil { return err }
}
err := store.RenameBucket(ctx, oldName, newName)
Defensive patterns

Strategy: validation

Validate before calling

b := store.Bucket(bucketName)
if b != nil && !b.IsReadOnly() {
    return fmt.Errorf("bucket %q must be set read-only before rename", bucketName)
}

Type guard

func bucketIsReadOnly(b *lsmkv.Bucket) bool { return b != nil && b.IsReadOnly() }

Try / catch

if err := store.RenameBucket(ctx, a, b); err != nil {
    if strings.Contains(err.Error(), "must be in read-only mode") {
        return fmt.Errorf("put bucket in read-only (quiesce writes) before rename: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Store.RenameBucket on a bucket that is still writable — i.e. the caller did not put the bucket (or its shard) into read-only state before renaming.

Common situations: Migration code forgetting the read-only step; renaming a tenant shard bucket while writes are still flowing; calling rename during active ingest instead of after quiescing writes.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/be32d943d672dc46. Report an issue: GitHub.