Skip to content

repo update-packages fails every project in a fresh clone: it lists outdated packages before restoring, so dotnet list package finds no assets file #279

Open

Description

@matt-edmondson

What's wrong

In KtsuTools.Repo/RepoService.cs:1120-1143, UpdateSolutionPackagesAsync handles each project in this order:

  1. UpdateProjectOutdatedPackagesAsync runs dotnet list "<proj>" package --outdated --format json (line 1149).
  2. Only then does it run dotnet restore "<proj>" (line 1132).

dotnet list package does not restore. If obj/project.assets.json is missing, it reports "No assets file was found for <proj>. Please run restore before running this command." That shows up as a non-zero exit code, a JSON problems entry, or both. Either one sends line 1153 down the failure path:

if (outdatedResult.ExitCode != 0 || !OutdatedPackage.TryParse(...)) { WriteUpdateFailure(...); return (0, 1); }

RepoUpdatePackagesTests.TryParseRejectsOutputThatIsNotTheExpectedJson (KtsuTools.Test/RepoUpdatePackagesTests.cs:96) asserts that this exact "No assets file" output is rejected. The rejection is correct. The problem is that the command itself produces that state for every project that has never been restored.

Failure scenario

  1. Clone a workspace, or run git clean -xdf.
  2. Run ktsu repo update-packages --path <ws>.
  3. Every project prints "Failed to list outdated packages in X.csproj", nothing is updated, and the run exits 1.
  4. Each project gets restored after its failed listing, so the same command works the second time.

There is a related case after a git pull that changed package versions: the stale assets file makes --outdated report against the old resolved versions.

Suggested fix / acceptance criteria

  • Restore each project, or the solution once, before running dotnet list ... --outdated. If that restore fails, report it as that step's failure.
  • Remove the restore that runs after the update, or keep it only as a final check, since dotnet add package already restores.
  • Add a test with a fake dotnet whose list package fails until restore has run for that project. UpdatePackagesAsync should update the outdated package and return 0.

Activity

  1. matt-edmondson commented on Oct 17, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    Notes: The command fails on every never-restored project, and a fresh clone or CI checkout is exactly that state. So the first run always fails, and it only works on a second run. The fix is small: restore before dotnet list --outdated. The proposed fake-dotnet test fits the existing RepoUpdatePackagesTests setup.


    Generated by Claude Code

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions