You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
and guards it with catch (ApiException) { // skip this owner }. But .Result wraps failures in AggregateException, so the ApiException handler never matches and the error escapes.
The step before it, SyncGitHubOwnerInfo (~L990), calls GitHubClient.User.Get(owner).GetAwaiter().GetResult() with no handler at all, so a 404 there also escapes.
Failure scenario
"Add New GitHub Owner" with a typo, or
"Scan > GitHub Owners" when a saved owner was renamed or deleted, its PAT was revoked, or the API rate limit is used up
→ NotFoundException / AuthorizationException / RateLimitExceededException (wrapped in AggregateException in the repo-listing path) comes out of an ImGui menu/popup callback on the render thread. The scan stops partway, and the app probably goes down with it. The owner has already been added to Options.GitHubOwners. If that was saved, every later owner scan fails the same way, and there is no UI to remove the owner.
Verified with a scratch test that points Octokit's GitHubClient at a local HttpListener returning 404:
GetAllForUser("nobody").Result threw System.AggregateException (inner Octokit.NotFoundException), and catch (Octokit.ApiException) did not catch it.
Replace .Result with .GetAwaiter().GetResult() (or await) so ApiException is thrown unwrapped.
Move the User.Get call into the same guarded region, or catch ApiException in SyncGitHubOwnerInfo too. Also catch HttpRequestException so going offline is handled.
Log the skipped owner and the reason rather than swallowing it silently.
Adding a nonexistent owner, or scanning with one owner returning 404/401/403 or a rate-limit error, logs a message, skips that owner, and carries on with the rest.
What's wrong
SyncGitHubRepoInfoForOwner(ProjectDirector/ProjectDirector.cs~L1006, L1010) fetches repos with.Result:and guards it with
catch (ApiException) { // skip this owner }. But.Resultwraps failures inAggregateException, so theApiExceptionhandler never matches and the error escapes.The step before it,
SyncGitHubOwnerInfo(~L990), callsGitHubClient.User.Get(owner).GetAwaiter().GetResult()with no handler at all, so a 404 there also escapes.Failure scenario
→
NotFoundException/AuthorizationException/RateLimitExceededException(wrapped inAggregateExceptionin the repo-listing path) comes out of an ImGui menu/popup callback on the render thread. The scan stops partway, and the app probably goes down with it. The owner has already been added toOptions.GitHubOwners. If that was saved, every later owner scan fails the same way, and there is no UI to remove the owner.Verified with a scratch test that points Octokit's
GitHubClientat a localHttpListenerreturning 404:GetAllForUser("nobody").ResultthrewSystem.AggregateException(innerOctokit.NotFoundException), andcatch (Octokit.ApiException)did not catch it.User.Get(...).GetAwaiter().GetResult()threwOctokit.NotFoundException.Suggested fix
.Resultwith.GetAwaiter().GetResult()(orawait) soApiExceptionis thrown unwrapped.User.Getcall into the same guarded region, or catchApiExceptioninSyncGitHubOwnerInfotoo. Also catchHttpRequestExceptionso going offline is handled.SyncGitHubOwnerInfowithoutApplyCredentialsfirst, so the new owner is queried with whatever credentials the previous scan left on the shared client. This is the same leak GitHub credentials from one owner leak into the scan of the next, misdirecting private-repo lookups #426 fixed for the scan loop.Acceptance criteria