denoland / denoland/deploy_feedback

CLI: publish crashes with 'Top-level await promise never resolved' when watchUntilReady closes early

Open Beginner friendly
#949 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.