Skip to content

common.ps1 uses .NET Core-only TrimEndingDirectorySeparator, breaking SPECIFY_INIT_DIR on Windows PowerShell 5.1 #3749

Description

@kurtvalcorza

Summary

scripts/powershell/common.ps1 resolves the project root with a .NET Core-only API, which is unavailable on Windows PowerShell 5.1 (.NET Framework). When SPECIFY_INIT_DIR is set, root resolution throws before any Spec Kit command can run.

The same file already documents this exact incompatibility — and then avoids it correctly 150 lines later.

The inconsistency

scripts/powershell/common.ps1:60:

$initRoot = [System.IO.Path]::TrimEndingDirectorySeparator($resolved.Path)

scripts/powershell/common.ps1:212-214:

# TrimEnd (not [Path]::TrimEndingDirectorySeparator, which is .NET Core
# only) keeps this working on Windows PowerShell 5.1 / .NET Framework.
$featureDirTrimmed = $featureDir.TrimEnd('/', '\')

So the codebase already knows TrimEndingDirectorySeparator is .NET Core only, and line 60 uses it anyway.

Impact

Windows PowerShell 5.1 users who set SPECIFY_INIT_DIR hit a Method invocation failed error during project-root resolution, before the requested command executes. Users on PowerShell 7+ are unaffected, which is likely why this hasn't surfaced widely.

Suggested fix

Use the same normalization the file already endorses:

$initRoot = $resolved.Path.TrimEnd('/', '\')

The stated no-op semantics still hold: TrimEnd is a no-op on a path with no trailing separator. Note it differs on a bare drive root (C:\C:), which is the one case worth a guard if that path is reachable here.

Version

Reproduced on main @ c0fe0e4 (v0.14.2).

Found by an automated review pass over a vendored copy in a downstream project; verified against upstream main before filing.

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