Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dotnet run gives ArgumentOutOfRangeException error at TryGetTargetArchitecture method #23004

Closed
ponlawat-w opened this issue Dec 10, 2021 · 16 comments · Fixed by #24518
Closed
Assignees
Labels
Area-NetSDK good first issue Issues that would be a good fit for someone new to the repository. Narrow in scope, well-defined.
Milestone

Comments

@ponlawat-w
Copy link

Describe the bug

I installed .NET 6.0.1 SDK, and turned out that I cannot use command dotnet run at all, because it keeps giving me ArgumentOutOfRangeException. However, it is successful to run dotnet build then dotnet [path-to-dll] or dotnet watch run instead.
The full error message:

System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string. (Parameter 'startIndex')
   at System.String.Substring(Int32 startIndex, Int32 length)
   at Microsoft.DotNet.Tools.Run.RunCommand.TryGetTargetArchitecture(String runtimeIdentifier, Nullable`1& targetArchitecture)
   at Microsoft.DotNet.Tools.Run.RunCommand.GetTargetCommand()
   at Microsoft.DotNet.Tools.Run.RunCommand.Execute()
   at Microsoft.DotNet.Tools.Run.RunCommand.Run(String[] args)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)
   at Microsoft.DotNet.Cli.Program.Main(String[] args)

I have tried reinstalled using SDK Installer, Visual Studio Installer, and binaries zip file. All gave me the same result.

So I decided to pull the branch release/6.0.1xx from this repository, and modified the method TryGetTargetArchitecture in file src\Cli\dotnet\commands\dotnet-run\RunCommand.cs to add try&catch blocks as following to debug the behaviour of the command:

private static bool TryGetTargetArchitecture(string runtimeIdentifier, out Architecture? targetArchitecture)
{
    targetArchitecture = null;
    int separator = runtimeIdentifier.LastIndexOf("-");
    if (separator < 0)
    {
        return false;
    }

    try // ↓ MODIFIED FROM HERE
    {
        targetArchitecture = runtimeIdentifier.Substring(separator + 1).ToLowerInvariant() switch
        {
            "arm" => Architecture.Arm,
            "arm64" => Architecture.Arm64,
            "x64" => Architecture.X64,
            "x86" => Architecture.X86,
            _ => null
        };
    }
    catch
    {
        Console.WriteLine($"runtimeIdentifier = {runtimeIdentifier}");
        Console.WriteLine($"runtimeIdentifier.Length = {runtimeIdentifier.Length}");
        Console.WriteLine("runtimeIdentifier (CharArray) = " + String.Join(", ", runtimeIdentifier.ToCharArray().Select(x => $"'{x}'")));
        Console.WriteLine($"separator = {separator}");
    } // ↑ MODIFIED UNTIL HERE

    return targetArchitecture != null;
}

Here is the result:

runtimeIdentifier =
runtimeIdentifier.Length = 0
runtimeIdentifier (CharArray) =
separator = 0

runtimeIdentifier = win-x64
runtimeIdentifier.Length = 7
runtimeIdentifier (CharArray) = 'w', 'i', 'n', '-', 'x', '6', '4'
separator = 7

Oddly, it seems that String.LastIndexOf in my machine does not work as expected, and that cause it returns an incorrect character index.

I don't know what in my machine breaks the LastIndexOf, but it would be better if we have a safer logic in this method to prevent the similar problem.


Further technical details

  • Include the output of dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.100
 Commit:    9e8b04bbff

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.22000
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Users\xxx\exe\dotnet\sdk\6.0.100\

Host (useful for support):
  Version: 6.0.0
  Commit:  4822e3c3aa

.NET SDKs installed:
  6.0.100 [C:\Users\xxx\exe\dotnet\sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 6.0.0 [C:\Users\xxx\exe\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 6.0.0 [C:\Users\xxx\exe\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.WindowsDesktop.App 6.0.0 [C:\Users\xxx\exe\dotnet\shared\Microsoft.WindowsDesktop.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-NetSDK untriaged Request triage from a team member labels Dec 10, 2021
@ponlawat-w
Copy link
Author

According to `LastIndexOf`` documentation here:

Note: This code example was executed on a console whose user interface 
culture is "en-US" (English-United States).

This code example produces the following results:

Find the last occurrence of a character using different values of StringComparison.
The current culture is "en-US" - English (United States).
Search for the string "Å" in the string "A Cheshire ca°t"

Part 1: Start index and count are specified.
Comparison: CurrentCulture               Location:  -1
Comparison: CurrentCultureIgnoreCase     Location:  12
Comparison: InvariantCulture             Location:  -1
Comparison: InvariantCultureIgnoreCase   Location:  12
Comparison: Ordinal                      Location:  -1
Comparison: OrdinalIgnoreCase            Location:  -1

Part 2: Start index is specified.
Comparison: CurrentCulture               Location:  -1
Comparison: CurrentCultureIgnoreCase     Location:  12
Comparison: InvariantCulture             Location:  -1
Comparison: InvariantCultureIgnoreCase   Location:  12
Comparison: Ordinal                      Location:  -1
Comparison: OrdinalIgnoreCase            Location:  -1

Part 3: Neither start index nor count is specified.
Comparison: CurrentCulture               Location:  -1
Comparison: CurrentCultureIgnoreCase     Location:  12
Comparison: InvariantCulture             Location:  -1
Comparison: InvariantCultureIgnoreCase   Location:  12
Comparison: Ordinal                      Location:  -1
Comparison: OrdinalIgnoreCase            Location:  -1

It seems that String.LastIndexOf behaves differently depends on locale, which in my case it is in Thai.
So it should be instead as following to support users from different cultural environment:

int separator = runtimeIdentifier.LastIndexOf("-", StringComparison.InvariantCulture);

I have tried rebuilt with the above fix, and the command dotnet run now works in my machine.

@timelessnesses
Copy link

have this error too

@Pathomkarn
Copy link

ผมพบเจอปัญหาแบบเดียวกันเลยครับ ไม่ทราบว่าผมต้องทำยังไงหรอครับ
image

@ponlawat-w
Copy link
Author

Temporary solution for Windows users until newer .NET version fix this issue:

Firstly, create a file name dotnet.ps1 with following content…

$env:DOTNET_SYSTEM_GLOBALIZATION_INVARIANT='True'
& 'C:\Program Files\dotnet\dotnet.exe' @args

If necessary, update 'C:\Program Files\...' to be where your dotnet is installed.

Then, add path of the directory which contains dotnet.ps1 to environment variable PATH, make sure that the path comes before installed dotnet directory.

Command dotnet in terminal should be now bypassed to dotnet.ps1 for setting global culture info before calling dotnet.exe.


(in Thai)

@Pathomkarn วิธีแก้ชั่วคราวนะครับ ให้สร้างไฟล์ชื่อ dotnet.ps1 ไว้ในโฟลเดอร์ไหนก็ได้ โดยข้างในมีสคริปต์ด้านบนอยู่ ซึ่งอาจเปลี่ยนส่วน 'C:\Program Files\...' ในสคริปต์ให้เป็นตำแหน่งของโฟลเดอร์ที่ติดตั้งตัว dotnet
หลังจากนั้น ให้ไปแก้ไข environment variable หาตัวแปรที่ชื่อ PATH และแทรกตำแหน่งที่ตั้งโฟลเดอร์ที่มีไฟล์ dotnet.ps1 ไปให้มาก่อนโฟลเดอร์จริงของตัว dotnet ครับ

@ponlawat-w
Copy link
Author

👆
The above one is not yet a good solution if your project has locale-sensitive sorting / string comparing. All the cultures will be overwritten to invariant according to this document.

I will for now give up with 6.0 and going to keep my projects being 5.0 until there is a proper fix.

@Pathomkarn
Copy link

ถ้าผมถอยไปใช้.net version5 ความสามรถในการทำงานจะเหมือนกับตัว.net version6เลยไหมครับ?

ปล.โปรแกรมที่ผมต้องใช้คือ Visual Studio Codeครับ

@baronfel baronfel added this to the 6.0.3xx milestone Feb 2, 2022
@baronfel baronfel added up-for-grabs and removed untriaged Request triage from a team member labels Feb 2, 2022
@baronfel
Copy link
Member

baronfel commented Feb 2, 2022

We should take the suggested fix as soon as possible - RIDs should always be parsed/manipulated in Invariant ways in the SDK. I've marked the issue as up-for-grabs if anyone from the community would like to contribute it. Tests would need to demonstrate that this function works for several different cultures set as the CurrentCulture/CurrentUICulture, ideally including several of those that use non-ASCII character sets, and some that use right-to-left encodings.

@dsplaisted
Copy link
Member

Looks like there are a couple of other places with the same issue:

private static string GetOsFromRid(string rid) => rid.Substring(0, rid.LastIndexOf("-"));
private static string GetArchFromRid(string rid) => rid.Substring(rid.LastIndexOf("-") + 1, rid.Length - rid.LastIndexOf("-") - 1);

@dsplaisted dsplaisted added the good first issue Issues that would be a good fit for someone new to the repository. Narrow in scope, well-defined. label Mar 16, 2022
@gkulin gkulin linked a pull request Mar 24, 2022 that will close this issue
@dsplaisted
Copy link
Member

@ponlawat-w This should be fixed in the 6.0.300 SDK. Let us know if you run into any other issues.

@ponlawat-w
Copy link
Author

Thank you @dsplaisted @marcpopMSFT.

I have quickly updated dotnet to runtime version 6.3.0, but still got the error.

> dotnet --list-sdks
6.0.201 [C:\Program Files\dotnet\sdk]

> dotnet --list-runtimes
Microsoft.AspNetCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.3 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

> dotnet run --project MyProject
System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string. (Parameter 'startIndex')
   at System.String.Substring(Int32 startIndex, Int32 length)
   at Microsoft.DotNet.Tools.Run.RunCommand.TryGetTargetArchitecture(String runtimeIdentifier, Nullable`1& targetArchitecture)
   at Microsoft.DotNet.Tools.Run.RunCommand.GetTargetCommand()
   at Microsoft.DotNet.Tools.Run.RunCommand.Execute()
   at Microsoft.DotNet.Tools.Run.RunCommand.Run(String[] args)
   at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)

I am still busy these days, so I will investigate more when I have time, and open a new issue if neccessary.

@baronfel
Copy link
Member

baronfel commented Apr 6, 2022

@ponlawat-w note that you may be on runtime 6.0.3, but this change was a change in the SDK, and the 6.0.300 SDK releases haven't happened quite yet. So keep your eyes peeled for that!

@ponlawat-w
Copy link
Author

@baronfel Oh, OK. I must have been confused with the number. Thank you for clarifying. I am looking forward to the new release.

@marcpopMSFT
Copy link
Member

This document will help with SDK versioning. https://docs.microsoft.com/en-us/dotnet/core/porting/versioning-sdk-msbuild-vs Basically, the SDK matches the major version of .NET but does feature releases with VS hence the hybrid version numbers that don't match either.

@lsomchai
Copy link

I found this solution when looking for the dotnet tool install fail. The error message also make me don't understand what a related to startIndex. My dotnet SDK version is 7.0.305 on Windows 11 Thai.

@famasf1
Copy link

famasf1 commented Jul 28, 2023

This issue still present as of .NET version 7.0.306. Might be time to reopen this up. i'm still not sure how much this would affect my workflow. Let's hope for a minimal effect long-terms wise
.
I'm also Thai. So this issue must be something related to our localization encoding?

@aisuuuice
Copy link

Hello, This issue still present as of .NET version 8.0.101.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-NetSDK good first issue Issues that would be a good fit for someone new to the repository. Narrow in scope, well-defined.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants