denoland / denoland/deploy_feedback
CLI: publish crashes with 'Top-level await promise never resolved' when watchUntilReady closes early
- Dominant language
- No language data
- Stars
- 79
- Forks
- 5
- PR merge metrics
- No merged PRs in 30d
Description
> **Disclosure:** this report was written by Claude (an AI coding assistant) while diagnosing CI failures on behalf of Kyle June, who reviewed and submitted it.
## Summary
When the server closes the `revisions.watchUntilReady` subscription without ever delivering the `deno.diffsync.missing_hashes` label, the `@deno/deploy` CLI exits with a cryptic runtime crash instead of an error message:
```
You can view the revision here:
https://console.deno.com///builds/
error: Top-level await promise never resolved
await deployCommand.command("sandbox", sandboxCommand).reset().noExit()
^
at (https://jsr.io/@deno/deploy/0.0.9904/main.ts:40:5)
```
## Cause
In `deploy/publish.ts` (0.0.9904), the missing-hashes promise is only resolved from `onData` when the label arrives; `onError` reports properly, but **`onStopped` just unsubscribes without resolving or rejecting**:
```ts
const missingHashesPromise = Promise.withResolvers();
const sub = trpcClient.subscription("revisions.watchUntilReady", { … }, {
onData: (data) => { /* resolves only when missing_hashes label present */ },
onError: (err) => { sub.unsubscribe(); error(context, Deno.inspect(err)); },
onStopped: () => { sub.unsubscribe(); }, // <-- pending promise leaks
});
const missingHashes = await missingHashesPromise.promise; // never settles
```
When the stream stops early, the event loop drains with the top-level await still pending, and Deno reports the unresolved-promise crash — pointing at `main.ts`, with no indication the server declined the revision. We hit this repeatedly when a concurrent deploy of the same app made the backend abandon the revision (reported separately: #948).
## Expected
`onStopped` (and any path that abandons the watch) should reject the pending promise so the CLI can exit with a real, actionable message — e.g. "the server closed the build stream before reporting upload state; the revision may have been rejected — check or retry."
## Environment
`@deno/deploy` 0.0.9904, Deno 2.9.x, non-interactive CI (GitHub Actions).
Contributor guide
No contributing guide indexed for this repository
Research direction
Start in deploy/publish.ts at the revisions.watchUntilReady subscription and trace how missingHashesPromise is settled by onData, onError, and onStopped. Reproduce or inspect the early-stop path, then verify that the CLI exits with an actionable error rather than an unresolved top-level await when the stream closes without missing_hashes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- deno
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 74/100