fix(server): tell the user when a repository lookup finds nothing - #8371
fix(server): tell the user when a repository lookup finds nothing#8371msegec wants to merge 1 commit into
Conversation
A typo in the add-project GitHub path surfaced as 'The source control operation could not be completed.' because gh's repository resolution failure was classified as a generic command failure and the service replaced every provider detail with that sentence. gh stderr saying 'could not resolve to a repository' now classifies as repository-not-found, GitHubCli maps it to a dedicated error, and the provider opts curated constant details into the client-facing message through a new userDetail field. Free-text provider detail still never reaches the wire.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
Effect service conventions review: one finding on how the new user-facing detail is modeled. See inline comments.
Posted via Macroscope — Effect Service Conventions
| /** | ||
| * Set only to a compile-time constant that is safe to show the user. | ||
| * `detail` may quote provider output and stays out of client-facing | ||
| * errors; `userDetail` is the adapter's explicit opt-in to surface a | ||
| * curated explanation instead of the generic fallback. | ||
| */ | ||
| userDetail: Schema.optional(Schema.String), |
There was a problem hiding this comment.
userDetail adds a free-form, prose string field whose only guarantee is the surrounding comment, and it duplicates detail at its single production construction site (GitHubSourceControlProvider.getRepositoryCloneUrls passes userDetail: error.detail). The distinction it encodes ("this failure is a repository lookup miss, and here is the sentence for it") already exists structurally as GitHubRepositoryNotFoundError / VcsProcessExitFailureKind.
Consider modeling it structurally instead of threading text: a dedicated not-found error class (or a reason literal on SourceControlRepositoryError) whose detail/message is derived from the tag/reason, keeping the provider error as cause. That keeps error attributes bounded and the caller-visible sentence owned by the error type rather than copied through two layers.
Posted via Macroscope — Effect Service Conventions
| // Provider `detail` may quote provider output, so only the curated | ||
| // `userDetail` opt-in reaches the client; everything else stays | ||
| // behind the generic sentence. | ||
| detail: | ||
| (isSourceControlProviderError(cause) ? cause.userDetail : undefined) ?? | ||
| "The source control operation could not be completed.", |
There was a problem hiding this comment.
The wrapper's detail — and therefore SourceControlRepositoryError.message — is now taken from the cause's string field rather than from the wrapper's own structural attributes. Suggest classifying the provider failure here (e.g. on its tag/failureKind) into a structured reason or a distinct not-found error class, and deriving the user-facing sentence from that, so the message stays independent of provider-supplied text.
Posted via Macroscope — Effect Service Conventions
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This is a focused GitHub repository-lookup error-message fix with limited runtime impact and focused tests. It also changes a shared error contract by propagating optional prose between layers, and unresolved design concerns about that representation warrant human review. You can add or adjust custom eligibility rules. Learn more. |
|
Folded into #8329, which already covers the add-project lookup flow. |
Typing a repository path that does not resolve in the add-project GitHub flow showed "Source control repository operation lookupRepository failed for github: The source control operation could not be completed." The real cause, gh answering "Could not resolve to a Repository", was classified as a generic command failure, and the repository service replaces every provider detail with that generic sentence.
Three small pieces fix it end to end. VcsProcess now classifies gh's repository resolution stderr as a dedicated repository-not-found kind. GitHubCli maps that kind to a new GitHubRepositoryNotFoundError whose detail says "Repository not found. Check the owner/repo path and try again." The GitHub provider opts its compile-time constant details into a new userDetail field on SourceControlProviderError, and the repository service surfaces userDetail to the client while free-text provider detail still never reaches the wire. The toast now reads "Repository lookup failed: ... Repository not found. Check the owner/repo path and try again."
Verification: focused tests on VcsProcess (11), GitHubCli (13), SourceControlRepositoryService (10), GitLabCli (9), plus typecheck and lint for apps/server and packages/contracts.
Written by Claude Fable 5 in Claude Code.
Note
Low Risk
Error-mapping and user-facing messaging only; no auth, persistence, or clone/push behavior changes beyond clearer failures on lookup.
Overview
When a GitHub repository path does not resolve during add-project lookup, users now see a specific “repository not found” message instead of the generic “source control operation could not be completed” toast.
VCS classification:
ghstderr that mentions resolving a Repository is classified asrepository-not-found(distinct from pull-requestnot-found). That kind maps through contracts to a short server-side detail (“Repository not found.”).GitHub CLI layer: A new
GitHubRepositoryNotFoundErrorcarries the user-facing line: check the owner/repo path and try again.Safe client messaging:
SourceControlProviderErrorgains optionaluserDetailfor compile-time-safe text. The GitHub provider setsuserDetailongetRepositoryCloneUrlsfailures.SourceControlRepositoryServiceprefersuserDetailfor the repository errordetailsent to the client; raw providerdetail(which may echo CLI output) still does not leak whenuserDetailis omitted.GitLab continues to fold
repository-not-foundinto its generic command error—no dedicated MR/repo split there in this change.Reviewed by Cursor Bugbot for commit 33f179f. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Surface a user-safe message when repository lookup finds nothing
"repository-not-found"literal toVcsProcessExitFailureKindin vcs.ts and classifiesghexits whose stderr contains "could not resolve to a repository" as this kind in VcsProcess.ts.GitHubRepositoryNotFoundErrorin GitHubCli.ts, which carries a curated detail string.userDetailfield toSourceControlProviderErrorin sourceControl.ts, and threads it throughGitHubSourceControlProviderand SourceControlRepositoryService.ts so service errors surface the provider's detail instead of a generic message.GitHubCliErrorunion gains a new_tagvariantGitHubRepositoryNotFoundError; any out-of-tree consumers narrowing on that union need to handle the new tag.Macroscope summarized 33f179f.