tailscale/tailscale · error

tailnet lock is not enabled

Error message

tailnet lock is not enabled

What it means

runTailnetLockRemove (cmd/tailscale/cli/tailnet-lock.go:347) checks st.Enabled after fetching TailnetLockStatus; if tailnet lock is not enabled there are no trusted keys to remove, so the command returns this error before attempting any modification.

Source

Thrown at cmd/tailscale/cli/tailnet-lock.go:347

		fs.BoolVar(&nlRemoveArgs.resign, "re-sign", true, "resign signatures which would be invalidated by removal of trusted signing keys")
		return fs
	})(),
}

func runTailnetLockRemove(ctx context.Context, args []string) error {
	removeKeys, _, err := parseTLArgs(args, true, false)
	if err != nil {
		return err
	}
	if len(removeKeys) == 0 {
		return fmt.Errorf("missing argument, expected one or more tailnet lock keys")
	}
	st, err := localClient.TailnetLockStatus(ctx)
	if err != nil {
		return fixTailscaledConnectError(err)
	}
	if !st.Enabled {
		return errors.New("tailnet lock is not enabled")
	}
	if len(st.TrustedKeys) == 1 {
		return errors.New("cannot remove the last trusted signing key; use 'tailscale lock disable' to disable tailnet lock instead, or add another signing key before removing one")
	}

	if nlRemoveArgs.resign {
		// Validate we are not removing trust in ourselves while resigning. This is because
		// we resign with our own key, so the signatures would be immediately invalid.
		for _, k := range removeKeys {
			kID, err := k.ID()
			if err != nil {
				return fmt.Errorf("computing KeyID for key %v: %w", k, err)
			}
			if bytes.Equal(st.PublicKey.KeyID(), kID) {
				return errors.New("cannot remove local trusted signing key while resigning; run command on a different node or with --re-sign=false")
			}
		}

View on GitHub (pinned to cfe32b8be6)

Solutions

  1. Verify with `tailscale lock status` that lock is enabled
  2. If you intended to start using lock, run `tailscale lock init ...` first
  3. If lock was intentionally disabled, drop the remove step from your runbook

Example fix

# before
$ tailscale lock remove tlpub:...
# after
$ tailscale lock init tlpub:... && tailscale lock remove tlpub:...
Defensive patterns

Strategy: validation

Validate before calling

st, err := localClient.TailnetLockStatus(ctx)
if err != nil {
    return err
}
if !st.Enabled {
    return errors.New("cannot remove keys: tailnet lock not enabled; run 'tailscale lock init' first")
}

Prevention

When it happens

Trigger: Running `tailscale lock remove tlpub:...` on a tailnet where lock was never initialized (st.Enabled == false), or after it was disabled.

Common situations: Running remove before init in setup scripts; lock was disabled with a disablement secret and someone retries stale remove commands; wrong tailnet (different account) where lock is off.

Related errors


AI-assisted analysis of tailscale/tailscale@cfe32b8be6 (2026-08-15). Data as JSON: /api/errors/ef351c63c5148eb9. Report an issue: GitHub.