k3s-io/k3s · critical

no bootstrap data found

Error message

no bootstrap data found

What it means

bootstrapKeyData lists keys with prefix '/bootstrap' and requires exactly one; zero entries yields this error. It is returned on paths that assume an initialized datastore (the caller expected existing bootstrap data to read or lock), so the datastore has never had bootstrap written or it was removed.

Source

Thrown at pkg/cluster/storage.go:135

		} else if errors.Is(err, rpctypes.ErrGRPCNotSupportedForLearner) {
			logrus.Debug("Skipping bootstrap data save on learner")
			return nil
		}
		return err
	}

	return nil
}

// bootstrapKeyData lists keys stored in the datastore with the prefix "/bootstrap", and
// will return the first such key. It will return an error if not exactly one key is found.
func bootstrapKeyData(ctx context.Context, storageClient store.ReadCloser) (*mvccpb.KeyValue, error) {
	bootstrapList, err := storageClient.List(ctx, "/bootstrap", 0)
	if err != nil {
		return nil, err
	}
	if len(bootstrapList) == 0 {
		return nil, errors.New("no bootstrap data found")
	}
	if len(bootstrapList) > 1 {
		return nil, errors.New("found multiple bootstrap keys in storage")
	}
	return &bootstrapList[0], nil
}

// storageBootstrap loads data from the datastore's bootstrap key into the
// ControlRuntimeBootstrap struct. The storage key and encryption passphrase are both derived
// from the join token. If no bootstrap key exists, indicating that data needs to be written
// back to the datastore, this function will set c.saveBootstrap to true and create an empty
// bootstrap key as a lock. This function will not return successfully until either the
// bootstrap key has been locked, or data is read into the struct.
func (c *Cluster) storageBootstrap(ctx context.Context) error {
	if c.config.KineTLS {
		bootstrapCtx, cancel := context.WithCancel(ctx)
		defer func() {
			time.Sleep(time.Second)

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Verify the datastore endpoint is the one the cluster was created on and is reachable; an accidental empty DB is the most common cause.
  2. If the datastore is genuinely empty, reinitialize: remove stale node state (token file/db dir) and start the first server with --cluster-init.
  3. Restore the external database or etcd from a backup that contains the /bootstrap key.
Defensive patterns

Strategy: validation

Validate before calling

// Pre-start check that the datastore actually contains bootstrap data:
list, err := storageClient.List(ctx, "/bootstrap", 0)
if err != nil { return err }
if len(list) == 0 {
	return errors.New("datastore has no /bootstrap keys: wrong endpoint or wiped DB; reinitialize with --cluster-init")
}

Try / catch

if err := c.storageBootstrap(ctx); err != nil {
	if strings.Contains(err.Error(), "no bootstrap data found") {
		// verify --datastore-endpoint points at the ORIGINAL database; if truly empty, reinit
	}
	return err
}

Prevention

When it happens

Trigger: storageBootstrap/getBootstrapKeyFromStorage running against a datastore where no '/bootstrap/*' key exists while the server believes it is joining or reading an existing cluster (token file exists but datastore was wiped); kine endpoint pointing at an empty external database.

Common situations: External SQL database recreated/emptied while node credentials (token file, certs) still exist; etcd restored without the bootstrap key; wrong --datastore-endpoint pointing at a fresh database.

Related errors


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/6014678c54f4058b. Report an issue: GitHub.