can1357/oh-my-pi · error · Error

GitHub release ${expectedTag} is a draft, not a published re

Error message

GitHub release ${expectedTag} is a draft, not a published release

What it means

Binary releases must be fully published; drafts have no final assets and are not downloadable by the general public. resolveReleaseBinaryAsset rejects any release whose draft flag is not exactly false with this error, even if the tag matches. This stops the updater from attempting to fetch assets that do not exist yet.

Source

Thrown at packages/coding-agent/src/cli/update-cli.ts:203

 * Draft releases are always rejected. Prereleases are rejected unless
 * `options.allowPrerelease` is set, which the canary channel passes: canary
 * GitHub releases are published as prereleases, and the exact-tag match below
 * still pins the download to the specific requested version.
 */
export function resolveReleaseBinaryAsset(
	release: unknown,
	expectedTag: string,
	binaryName: string,
	options: { allowPrerelease?: boolean } = {},
): ReleaseBinaryAsset {
	if (!isRecord(release)) {
		throw new Error("Invalid GitHub release metadata");
	}
	if (release.tag_name !== expectedTag) {
		throw new Error(`GitHub release tag mismatch: expected ${expectedTag}`);
	}
	if (release.draft !== false) {
		throw new Error(`GitHub release ${expectedTag} is a draft, not a published release`);
	}
	if (release.prerelease !== false && !options.allowPrerelease) {
		throw new Error(`GitHub release ${expectedTag} is a prerelease; only canary updates install prerelease assets`);
	}
	if (!Array.isArray(release.assets)) {
		throw new Error(`GitHub release ${expectedTag} has no asset list`);
	}

	const matches = release.assets.filter(asset => isRecord(asset) && asset.name === binaryName);
	if (matches.length !== 1) {
		throw new Error(`GitHub release ${expectedTag} has ${matches.length} assets named ${binaryName}`);
	}

	const asset = matches[0];
	if (!isRecord(asset) || asset.state !== "uploaded") {
		throw new Error(`GitHub release asset ${binaryName} is not fully uploaded`);
	}
	if (typeof asset.size !== "number" || !Number.isSafeInteger(asset.size) || asset.size <= 0) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Wait until the release is published on the GitHub releases page and retry the update.
  2. Verify on the releases page that the tag shows as published (not draft).
  3. If you need pre-publish binaries, switch to the canary channel which installs prerelease assets once published as prereleases.
  4. If it stays a draft indefinitely, report/check the release pipeline — the updater will never install from a draft.
Defensive patterns

Strategy: validation

Validate before calling

if (release.draft !== false) {
  throw new Error(`${release.tag_name} is still a draft; wait for publish before updating`);
}

Type guard

function isPublished(v: unknown): v is { tag_name: string; draft: false; prerelease: boolean; assets: unknown[] } {
  return typeof v === "object" && v !== null && (v as any).draft === false;
}

Try / catch

try {
  const asset = resolveReleaseBinaryAsset(release, expectedTag, binaryName);
} catch (err) {
  if (err instanceof Error && err.message.includes("is a draft")) {
    console.error("Release not published yet — retry later or pin to the previous release.");
  }
  throw err;
}

Prevention

When it happens

Trigger: Running an update while the target release is still in draft state on GitHub — typically right after maintainers created/uploaded the release but before publishing, or when a release was reverted back to draft.

Common situations: Updating minutes after a release announcement while assets are still being finalized; canary/stable channel pointed at an unpublished tag; release automation that uploads assets but has not hit publish yet.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/1c66ccd897573a79. Report an issue: GitHub.