Skip to content

tiup link tiup:<version> breaks tiup update --self and tiup unlink tiup leaves TiUP unavailable #2706

@sgykfjsm

Description

@sgykfjsm

Bug Report

Please answer these questions before submitting your issue. Thanks!

  1. What did you do?

After running tiup link tiup:<version>, ~/.tiup/bin/tiup is replaced with a symlink to the selected TiUP component binary.

$ ls -l ~/.tiup/bin/
total 11848
-rw-r--r--. 1 ec2-user ec2-user     7275 May 11 06:18 7b8e153f2e2d0928.root.json
-rw-r--r--. 1 ec2-user ec2-user     7275 May 11 06:58 root.json
-rwxr-xr-x. 1 ec2-user ec2-user 12112056 Apr 10 04:00 tiup

$ tiup link tiup:v1.16.5
package tiup provides these executables: tiup

$ ls -l ~/.tiup/bin/
total 16
-rw-r--r--. 1 ec2-user ec2-user 7275 May 11 06:18 7b8e153f2e2d0928.root.json
-rw-r--r--. 1 ec2-user ec2-user 7275 May 11 06:58 root.json
lrwxrwxrwx. 1 ec2-user ec2-user   49 May 11 06:58 tiup -> /home/ec2-user/.tiup/components/tiup/v1.16.5/tiup

In this state, running tiup update --self fails because TiUP checks whether the actual executed binary path is exactly the same as $TIUP_HOME/bin/tiup.

$ tiup update --self
Tiup install directory is: /home/ec2-user/.tiup/components/tiup/v1.16.5
Error: if you used some external package manager to install TiUP (e.g., brew), try upgrade with that

Additionally, running tiup unlink tiup removes the symlink from ~/.tiup/bin/tiup, but it does not restore the original TiUP binary. As a result, the tiup command itself becomes unavailable unless the user manually copies a TiUP binary back to ~/.tiup/bin/tiup.

$ tiup unlink tiup
/home/ec2-user/.tiup/bin/tiup will be removed.
 Do you want to continue? [y/N]:(default=N) y

$ ls -l ~/.tiup/bin/
total 16
-rw-r--r--. 1 ec2-user ec2-user 7275 May 11 06:18 7b8e153f2e2d0928.root.json
-rw-r--r--. 1 ec2-user ec2-user 7275 May 11 06:58 root.json

$ tiup --version
-bash: /home/ec2-user/.tiup/bin/tiup: No such file or directory

This can leave users unable to upgrade TiUP after using the documented tiup link tiup:<version> workflow.

  1. What did you expect to see?

tiup update --self should either:

  • work correctly when ~/.tiup/bin/tiup is a symlink managed by tiup link, or
  • show a clear message explaining that TiUP is currently linked and how to recover or update it safely.

Also, if tiup unlink tiup is used after linking TiUP itself, I expected one of the following behaviors:

  • restore the previous executable binary in ~/.tiup/bin/tiup, or
  • print clear recovery instructions before/after removing the symlink.
  1. What did you see instead?

tiup update --self fails with the following error:

$ tiup update --self
Tiup install directory is: /home/ec2-user/.tiup/components/tiup/v1.16.5
Error: if you used some external package manager to install TiUP (e.g., brew), try upgrade with that

After that, running:

$ tiup unlink tiup

removes ~/.tiup/bin/tiup, but does not restore the original binary. Therefore, tiup is no longer available from the normal command path.

The user can recover manually by copying a binary such as:

cp ~/.tiup/components/tiup/<version>/tiup ~/.tiup/bin/tiup

However, this recovery step does not seem to be documented or suggested by the command output.

Possible fixes

  • Make tiup update --self handle TiUP-managed symlinks correctly
    • For example, by resolving symlinks before comparing the expected TiUP binary path with the actual executable path.
  • When tiup link tiup:<version> replaces ~/.tiup/bin/tiup, keep a backup of the original binary and restore it automatically on tiup unlink tiup.
  • If the current behavior is intentional, document the limitation clearly and show recovery steps, such as copying a TiUP binary from ~/.tiup/components/tiup/<version>/tiup back to ~/.tiup/bin/tiup.
  • Improve the error message from tiup update --self so that it mentions the tiup link tiup:<version> case instead of only suggesting external package managers.
  1. What version of TiUP are you using (tiup --version)?
$ tiup --version
1.16.5 v1.16.5
Go Version: go1.25.0
Git Ref: master
GitHash: 9bdae0450713fe1b69b0d1a388ad4908276b1f98

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugCategorizes issue as related to a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions