Skip to content

install.ps1 aborts on upgrade: File.Replace rejects the null backup path #1354

Open

Description

@aenerv7

Description

Upgrading an existing Windows install with the documented one-liner aborts at the last step, after the
binary and PATH are already in place, and leaves ~/.config/thinkrail/install.json describing the
previous version.

irm https://raw.githubusercontent.com/JetBrains/thinkrail/main/install.ps1 | iex

from 0.3.2 to 0.4.0:

ThinkRail 0.4.0 (stable) installed.
PATH:           already configured
Invoke-Expression: Exception calling "Replace" with "3" argument(s): "The path is empty. (Parameter 'path')"

thinkrail --version reports 0.4.0, but the closing Run: / Update later: / Uninstall: lines never
print and the metadata still reports 0.3.2.

Steps to reproduce

  1. Install 0.4.0 with the one-liner.
  2. Run the same one-liner again over that install.
  3. The second run ends with the exception above.

Minimal check, independent of the installer:

$d = Join-Path $env:TEMP ([guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory $d | Out-Null
$new = Join-Path $d 'new'; $dst = Join-Path $d 'old'
Set-Content $new 'a'; Set-Content $dst 'b'
[System.IO.File]::Replace($new, $dst, $null)                 # throws
[System.IO.File]::Replace($new, $dst, [NullString]::Value)   # works

Expected behavior

The second install replaces install.json with the new version and prints its closing lines.

Actual behavior

Install-ThinkRail writes the metadata with:

if (Test-Path -LiteralPath $metaFile) {
    [System.IO.File]::Replace($metaTemp, $metaFile, $null)
} else {
    [System.IO.File]::Move($metaTemp, $metaFile)
}

PowerShell binds $null to the string parameter as an empty string, so File.Replace receives ""
as the backup path instead of "no backup" and rejects it. PowerShell 7 reports The path is empty;
Windows PowerShell 5.1 reports The path is not of a legal form for the same call.

Only the Replace branch runs when install.json already exists, so a first install succeeds and every
install over an existing one fails at the last step.

Fix: pass a real null, [System.IO.File]::Replace($metaTemp, $metaFile, [NullString]::Value).
[NullString]::Value exists in both Windows PowerShell 5.1 and PowerShell 7.

Environment

  • OS: Windows 11 x64
  • Bun version (bun --version): 1.4.4
  • Node version (node --version): v26.13.0
  • ThinkRail version / commit: 0.4.0 (stable), upgrading from 0.3.2; PowerShell 7.6.9, also reproduced
    under Windows PowerShell 5.1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions