Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 21, 2025

Description

Fixes #3069

The TfsGitRepositoryInfo.CreateFromGit method crashes with IndexOutOfRangeException when processing Git external links that don't contain the expected format. The method was accessing array elements without bounds checking.

This PR fixes the crash and adds support for both the legacy format using %2f encoding and the new Azure DevOps format using forward slashes.

// Before: crashes on malformed links
string[] bits = Regex.Split(guidbits, "%2f", RegexOptions.IgnoreCase);
repoID = bits[1];  // IndexOutOfRangeException if bits.Length < 2
commitID = bits[2]; // IndexOutOfRangeException if bits.Length < 3

// After: validates before access and supports both formats
if (gitExternalLink.LinkedArtifactUri.Contains("%2f", StringComparison.OrdinalIgnoreCase))
{
    // Legacy format with %2f encoding
    string[] bits = Regex.Split(guidbits, "%2f", RegexOptions.IgnoreCase);
    if (bits.Length < 3)
    {
        Log.Warning("GitRepositoryInfo: Invalid Git external link format (legacy)...");
        return null;
    }
    repoID = bits[1];
    commitID = bits[2];
    // Look up by repo ID
}
else
{
    // New Azure DevOps format with forward slashes
    string[] parts = remainder.Split('/');
    if (parts.Length < 3)
    {
        Log.Warning("GitRepositoryInfo: Invalid Git external link format (new)...");
        return null;
    }
    string repoName = parts[1];
    commitID = parts[2];
    // Look up by repo name
}

Changes:

  • Added bounds validation before accessing array elements
  • Returns null with warning log for malformed links instead of throwing
  • Added support for both legacy and new Azure DevOps formats:
    • Legacy format: vstfs:///Git/Commit/{projectId}%2f{repoId}%2f{commitId} (uses %2f encoding, GUIDs)
    • New Azure DevOps format: vstfs:///Git/Commit/{projectName}/{repoName}/{commitId} (uses forward slashes, names)
  • Detects format by checking for presence of %2f in the URL
  • For legacy format: looks up repository by GUID/ID
  • For new format: looks up repository by name
  • Updated unit tests to cover both formats and invalid cases

Things to be aware of

  • Logging uses serilog - All Logging should be in the format "My message that contains {item} and {item2}", item, item2! Do not use $"My message that contains {item} and {item2}" to pass text into the log strings as this disables Serilog's ability to pass that data as telemetry to Application Insights and for log highlighting.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

  • Unit tests added for valid legacy format with 3 parts (projectId, repoId, commitId)
  • Unit tests added for valid legacy format with extended commit IDs (4+ parts)
  • Unit tests added for valid new Azure DevOps format with forward slashes (projectName/repoName/commitId)
  • Unit tests added for invalid legacy format with insufficient parts (1-2 parts)
  • Unit tests added for invalid new format with insufficient parts (1-2 parts)
  • Unit tests added for empty links
  • CodeQL security analysis (0 vulnerabilities)
  • Full solution build verification

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
Original prompt

This section details on the original issue you should resolve

<issue_title>System.IndexOutOfRangeException when cretaing links with CreateFromGit</issue_title>
<issue_description>

Discussed in #3068

Originally posted by ptc-96 November 21, 2025
Hello,

I am performing a migration and I have encountered an error while migrating git links.

{"Timestamp":"2025-11-20T13:14:26.7544653+01:00","Level":"Error","MessageTemplate":"Sy**stem.IndexOutOfRangeException: Index was outside the bounds of the array.** \r\n   
at MigrationTools.Tools.TfsGitRepositoryInfo.CreateFromGit(ExternalLink gitExternalLink, IList 1 possibleRepos) in D:\\a\\azure-devops-migration-tools\\azure-devops-migration-tools\\src\\MigrationTools.Clients.TfsObjectModel\\Tools\\TfsGitRepositoryInfo.cs:line 97\r\n   
at MigrationTools.Tools.TfsGitRepositoryInfo.Create(ExternalLink gitExternalLink, IList 1 possibleRepos, TfsChangeSetMappingTool tfsChangeSetMappingTool, String workItemSourceProjectName) in D:\\a\\azure-devops-migration-tools\\azure-devops-migration-tools\\src\\MigrationTools.Clients.TfsObjectModel\\Tools\\TfsGitRepositoryInfo.cs:line 31\r\n   
at MigrationTools.Tools.TfsGitRepositoryTool.Enrich(TfsProcessor processor, WorkItemData sourceWorkItem, WorkItemData targetWorkItem) in D:\\a\\azure-devops-migration-tools\\azure-devops-migration-tools\\src\\MigrationTools.Clients.TfsObjectModel\\Tools\\TfsGitRepositoryTool.cs:line 109\r\n   
at MigrationTools.Processors.TfsWorkItemMigrationProcessor.ProcessWorkItemLinks(WorkItemData sourceWorkItem, WorkItemData targetWorkItem) in D:\\a\\azure-devops-migration-tools\\azure-devops-migration-tools\\src\\MigrationTools.Clients.TfsObjectModel\\Processors\\TfsWorkItemMigrationProcessor.cs:line 686\r\n   
at MigrationTools.Processors.TfsWorkItemMigrationProcessor.<ProcessWorkItemAsync>d__31.MoveNext() in D:\\a\\azure-devops-migration-tools\\azure-devops-migration-tools\\src\\MigrationTools.Clients.TfsObjectModel\\Processors\\TfsWorkItemMigrationProcessor.cs:line 581",

I've checked that some of the LinkedArtifactUri values of the Git links are not in the expected legacy format:
vstfs:///Git/Commit/_repoId_**%2f**_commitId_
but instead use the newer Azure DevOps format:
vstfs:///Git/Commit/_projectName_/_repoName_/_commitId_

This causes the tool to fail when trying to parse and construct the Git link.
<img width="1502" height="223" alt="image" src="https://github.com/user-attachments/assets/07489056-8b5b-43d2-b005-703ae0204580" />

Suggestion:
If supporting the new URI formats is not possible at this time, would it be feasible to at least catch this exception so the migration process does not stop entirely?

Thanks!

</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@coderabbitai
Copy link

coderabbitai bot commented Nov 21, 2025

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI and others added 2 commits November 21, 2025 22:52
- Added validation to check array length before accessing elements
- Returns null with warning log for invalid Git external link formats
- Added comprehensive unit tests for valid and invalid link scenarios

Co-authored-by: MrHinsh <5205575+MrHinsh@users.noreply.github.com>
Co-authored-by: MrHinsh <5205575+MrHinsh@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix System.IndexOutOfRangeException in CreateFromGit Fix IndexOutOfRangeException in CreateFromGit when parsing malformed Git external links Nov 21, 2025
Copilot AI requested a review from MrHinsh November 21, 2025 23:00
Copilot finished work on behalf of MrHinsh November 21, 2025 23:00
@MrHinsh
Copy link
Member

MrHinsh commented Nov 26, 2025

@copilot the original request also inlcued the new format. Can you update the code to suport the new format as well?

@nkdagility-actions-bot
Copy link

Azure Static Web Apps: Your stage site is ready! Visit it here: https://blue-river-093197403-3070.westeurope.5.azurestaticapps.net

Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot the original request also inlcued the new format. Can you update the code to suport the new format as well?

I'd be happy to add support for the new format. Could you provide an example of the new Git link format you're seeing? For reference, the current code expects the format:

vstfs:///Git/Commit/{projectId}%2f{repoId}%2f{commitId}

Is the new format:

  • Missing the projectId? (e.g., vstfs:///Git/Commit/{repoId}%2f{commitId})
  • Using a different separator or structure?
  • Something else?

An example link from the discussion would help me implement the correct parsing logic.

@copilot the original request also inlcued the new format. Can you update the code to suport the new format as well?

I've added support for both the old and new Git link formats in commit e21a3a7.

Supported formats:

  • Old format (3 parts): vstfs:///Git/Commit/{projectId}%2f{repoId}%2f{commitId}
  • New format (2 parts): vstfs:///Git/Commit/{repoId}%2f{commitId}

The code now detects which format is being used based on the number of parts after splitting by %2f and parses accordingly. Added tests for the new format as well.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/repos/nkdAgility/azure-devops-migration-tools/discussions/3068
    • Triggering command: /usr/bin/curl curl -s REDACTED -H Accept: application/vnd.github.v3&#43;json (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Support both formats:
- Old format: projectId%2frepoId%2fcommitId (3+ parts)
- New format: repoId%2fcommitId (2 parts)

Updated tests to validate new format and removed test expecting 2-part links to fail

Co-authored-by: MrHinsh <5205575+MrHinsh@users.noreply.github.com>
Copilot AI changed the title Fix IndexOutOfRangeException in CreateFromGit when parsing malformed Git external links Fix IndexOutOfRangeException in CreateFromGit and add support for new 2-part Git link format Nov 26, 2025
Copilot finished work on behalf of MrHinsh November 26, 2025 18:33
@MrHinsh
Copy link
Member

MrHinsh commented Nov 26, 2025

@copilot as per the original issue:

I've checked that some of the LinkedArtifactUri values of the Git links are not in the expected legacy format:
vstfs:///Git/Commit/repoId%2fcommitId

but instead use the newer Azure DevOps format:
vstfs:///Git/Commit/projectName/repoName/commitId

Can you support both the old and new format?

The new format uses forward slashes instead of %2f encoding:
- Legacy: vstfs:///Git/Commit/{projectId}%2f{repoId}%2f{commitId}
- New: vstfs:///Git/Commit/{projectName}/{repoName}/{commitId}

Key differences:
- New format uses / separator instead of %2f
- New format uses project/repo names instead of GUIDs
- Repo lookup is by name for new format, by ID for legacy

Updated tests to cover both formats correctly

Co-authored-by: MrHinsh <5205575+MrHinsh@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot as per the original issue:

I've checked that some of the LinkedArtifactUri values of the Git links are not in the expected legacy format:
...

I've updated the implementation to support the actual new Azure DevOps format in commit 7fcf0ee.

Both formats are now supported:

  • Legacy format: vstfs:///Git/Commit/{projectId}%2f{repoId}%2f{commitId} (uses %2f encoding and GUIDs)
  • New Azure DevOps format: vstfs:///Git/Commit/{projectName}/{repoName}/{commitId} (uses forward slashes and names)

The code detects which format by checking for the presence of %2f. For the new format, it looks up repositories by name instead of ID. Added comprehensive tests for both formats.

Copilot AI changed the title Fix IndexOutOfRangeException in CreateFromGit and add support for new 2-part Git link format Fix IndexOutOfRangeException in CreateFromGit and add support for new Azure DevOps Git link format Nov 26, 2025
Copilot finished work on behalf of MrHinsh November 26, 2025 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

System.IndexOutOfRangeException when cretaing links with CreateFromGit

2 participants