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
{{ message }}
Repository navigation
desktop: a pull request whose workflow failed to start disappears from the workspace view #9141
Open a workspace whose pull request has a check run with conclusion STARTUP_FAILURE (a workflow that cannot start) or STALE.
Look at the workspace's pull request status.
Expected
The pull request shows with its checks, the way #8962 asks for the v2 path.
Actual
No pull request. The legacy desktop gh path validates each pull request with GHPRResponseSchema, and parsePRListResponse (apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts:341-370) drops any item that fails validation — without a log for the list path.
Cause
The conclusion enum (apps/desktop/src/lib/trpc/routers/workspaces/utils/github/types.ts:9-21) lists 8 values and omits STARTUP_FAILURE and STALE, so safeParse fails for the whole pull request. parseChecks (pr-resolution.ts:417-451) and computeChecksStatus (:450-483) also lack STARTUP_FAILURE and would report it as pending once the schema accepts it.
Host-service has the same gap and it is being fixed separately: #8962, #8963. The mobile client and the v2 renderer already map STARTUP_FAILURE to failure.
Fix
Add both conclusions to the enum; map STARTUP_FAILURE to failure in parseChecks and computeChecksStatus. STALE stays pending, as in the host-service mapper.
In the legacy desktop gh path, if any check on a pull request finishes with STARTUP_FAILURE or STALE, the whole pull request disappears from the workspace view. The check-conclusion schema only accepts 8 values. One check with an unknown value fails validation for the entire PR object, and the list parser drops that PR without logging anything. Even after the schema accepts the new values, the two status mappers don't handle them correctly.
Affected code
apps/desktop/src/lib/trpc/routers/workspaces/utils/github/types.ts:9-20: the GHCheckContextSchema.conclusion enum has SUCCESS, FAILURE, CANCELLED, SKIPPED, TIMED_OUT, ACTION_REQUIRED, NEUTRAL and "". STARTUP_FAILURE and STALE are missing.
apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts:362-368: parsePRListResponse calls GHPRResponseSchema.safeParse(item) and only keeps items that pass. Failures are not logged. The single-PR path, parsePRResponse at :332-337, does log.
Both lookups use the list path, so both lose the PR:
findPRByHeadBranch (pr-resolution.ts:247)
findPRByHeadCommit (pr-resolution.ts:301)
pr-resolution.ts:417-448 (parseChecks): an unknown conclusion falls through to pending.
pr-resolution.ts:450-485 (computeChecksStatus): only PENDING, "", null and undefined count as pending. Anything else that isn't in the failure list counts as success.
Root cause
The root cause is the closed z.enum on conclusion in types.ts. Because statusCheckRollup is nested inside GHPRResponseSchema, one check with an unknown value fails safeParse for the whole PR. The silent continue in parsePRListResponse then hides the problem.
One correction to the issue's proposed fix: it says "STALE stays pending". That is true in parseChecks, where the default branch returns pending. In computeChecksStatus it is not: STALE matches neither branch, so a PR whose only non-success check is STALE would get rollup "success". If the intent is pending, add STALE to the pending branch at :472-478.
There is also a related mismatch. The host-service mapper (packages/host-service/src/runtime/pull-requests/utils/pull-request-mappers/pull-request-mappers.ts:165-168) maps ACTION_REQUIRED to failure. Desktop maps it to pending in parseChecks and to success in computeChecksStatus. It may be worth aligning while this code is open.
Elsewhere, STARTUP_FAILURE is already handled in:
the v2 renderer: apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/utils/toPullRequestDetail/toPullRequestDetail.ts:27
Manual: open a workspace on a branch whose PR has a workflow that can't start, for example one with an invalid workflow YAML, which gives STARTUP_FAILURE. With the legacy (non-v2) desktop path, no PR is shown. Running gh pr list --head <branch> --json statusCheckRollup shows the STARTUP_FAILURE conclusion.
import{GHPRResponseSchema}from"./types";test("accepts STARTUP_FAILURE and STALE conclusions",()=>{for(constconclusionof["STARTUP_FAILURE","STALE"]){constresult=GHPRResponseSchema.shape.statusCheckRollup.safeParse([{name: "ci",status: "COMPLETED", conclusion },]);expect(result.success).toBe(true);}});test("STARTUP_FAILURE rolls up to failure",()=>{expect(computeChecksStatus([{name: "ci",conclusion: "STARTUP_FAILURE"}]asGHPRResponse["statusCheckRollup"]),).toBe("failure");});test("STALE rolls up to pending",()=>{expect(computeChecksStatus([{name: "ci",conclusion: "STALE"}]asGHPRResponse["statusCheckRollup"]),).toBe("pending");});
(Adjust the statusCheckRollup access to match how GHPRResponseSchema is defined in types.ts.)
Suggested fix
Add "STARTUP_FAILURE" and "STALE" to the conclusion enum in types.ts. Optionally, also make it tolerant of future values, for example with a z.string() fallback, so a new GitHub conclusion can't hide a PR again.
In parseChecks, map STARTUP_FAILURE to failure.
In computeChecksStatus:
add STARTUP_FAILURE to the failure branch;
add STALE to the pending branch, because today it would count as success.
Log validation failures in parsePRListResponse, as parsePRResponse already does, so the next schema drift is visible.
Activity
github-actions commentedon Oct 30, 2026
The report holds up against the code.
Summary
In the legacy desktop
ghpath, if any check on a pull request finishes withSTARTUP_FAILUREorSTALE, the whole pull request disappears from the workspace view. The check-conclusion schema only accepts 8 values. One check with an unknown value fails validation for the entire PR object, and the list parser drops that PR without logging anything. Even after the schema accepts the new values, the two status mappers don't handle them correctly.Affected code
apps/desktop/src/lib/trpc/routers/workspaces/utils/github/types.ts:9-20: theGHCheckContextSchema.conclusionenum hasSUCCESS,FAILURE,CANCELLED,SKIPPED,TIMED_OUT,ACTION_REQUIRED,NEUTRALand"".STARTUP_FAILUREandSTALEare missing.apps/desktop/src/lib/trpc/routers/workspaces/utils/github/pr-resolution.ts:362-368:parsePRListResponsecallsGHPRResponseSchema.safeParse(item)and only keeps items that pass. Failures are not logged. The single-PR path,parsePRResponseat:332-337, does log.findPRByHeadBranch(pr-resolution.ts:247)findPRByHeadCommit(pr-resolution.ts:301)pr-resolution.ts:417-448(parseChecks): an unknown conclusion falls through topending.pr-resolution.ts:450-485(computeChecksStatus): onlyPENDING,"",nullandundefinedcount as pending. Anything else that isn't in the failure list counts as success.Root cause
The root cause is the closed
z.enumonconclusionintypes.ts. BecausestatusCheckRollupis nested insideGHPRResponseSchema, one check with an unknown value failssafeParsefor the whole PR. The silentcontinueinparsePRListResponsethen hides the problem.One correction to the issue's proposed fix: it says "
STALEstays pending". That is true inparseChecks, where the default branch returns pending. IncomputeChecksStatusit is not:STALEmatches neither branch, so a PR whose only non-success check isSTALEwould get rollup"success". If the intent is pending, addSTALEto the pending branch at:472-478.There is also a related mismatch. The host-service mapper (
packages/host-service/src/runtime/pull-requests/utils/pull-request-mappers/pull-request-mappers.ts:165-168) mapsACTION_REQUIREDtofailure. Desktop maps it topendinginparseChecksand tosuccessincomputeChecksStatus. It may be worth aligning while this code is open.Elsewhere,
STARTUP_FAILUREis already handled in:apps/desktop/src/renderer/routes/_authenticated/_dashboard/pull-requests/utils/toPullRequestDetail/toPullRequestDetail.ts:27apps/mobile/screens/(authenticated)/workspace/[id]/utils/pullRequest/types.ts:30Reproduction
Manual: open a workspace on a branch whose PR has a workflow that can't start, for example one with an invalid workflow YAML, which gives
STARTUP_FAILURE. With the legacy (non-v2) desktop path, no PR is shown. Runninggh pr list --head <branch> --json statusCheckRollupshows theSTARTUP_FAILUREconclusion.bun:testsketch (pr-resolution.test.tsalready importscomputeChecksStatus):(Adjust the
statusCheckRollupaccess to match howGHPRResponseSchemais defined intypes.ts.)Suggested fix
"STARTUP_FAILURE"and"STALE"to theconclusionenum intypes.ts. Optionally, also make it tolerant of future values, for example with az.string()fallback, so a new GitHub conclusion can't hide a PR again.parseChecks, mapSTARTUP_FAILUREtofailure.computeChecksStatus:STARTUP_FAILUREto the failure branch;STALEto the pending branch, because today it would count as success.parsePRListResponse, asparsePRResponsealready does, so the next schema drift is visible.Kitenite commentedon Oct 31, 2026
Closing: this is the v1 desktop path, which is being sunset. The v2 path maps
STARTUP_FAILUREto failure (#8963, #9161).