denoland/deno · error · AnyError

Failed to publish packages

Error message

Failed to publish {} packages:

What it means

When `deno publish` publishes a workspace with multiple packages and more than one package fails, the individual errors are combined into a single error with this header followed by one bulleted entry per package (each rendered with its full context chain, e.g. 'Failed to publish @scope/name: <cause>'). It is purely an aggregation wrapper: the real causes are the per-package errors listed below the header.

Solutions

  1. Read each `* <error>` bullet under the header; every bullet is an independent per-package failure with its full cause chain — fix them individually.
  2. Fix the most mechanical errors first (missing 'version', missing 'exports', slow types), then re-run `deno publish --dry-run` to re-validate all members cheaply.
  3. If a package failed only because its version already exists on jsr.io, bump that package's version (or use --allow-dirty/--skip-verification as appropriate) instead of republishing.
  4. Re-run `deno publish` after fixes; packages that succeeded are reported separately, so only failed ones retry.
Defensive patterns

Strategy: try-catch

Validate before calling

const cmd = new Deno.Command('deno', { args: ['publish', '--dry-run'] });
const { success, stderr } = await cmd.output();
if (!success) {
  // dry-run surfaces the same per-package errors before any upload
  throw new Error(new TextDecoder().decode(stderr));
}

Try / catch

try {
  await runDeno(['publish']);
} catch (e) {
  if (String(e.message).startsWith('Failed to publish')) {
    // each bullet after the header is one independent package failure
    const failures = e.message.split('\n\n* ').slice(1);
    for (const f of failures) fixOrReport(f);
  }
}

Prevention

When it happens

Trigger: A workspace publish where 2+ members each failed for independent reasons — e.g. one missing a `version` field, another having slow types, a third hitting a registry auth/409 version-already-exists error.

Common situations: First publish of a monorepo where several members share the same scaffolding mistake (all missing version, all missing exports map); partial network failure during a multi-package upload; one package already published at that version while another has an unrelated error.

Related errors


AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20). Data as JSON: /api/errors/cc8a2307a736524c. Report an issue: GitHub.

Appendix: source

Thrown at cli/tools/publish/mod.rs:1089

    }
    Err(combine_publish_errors(errors))
  }
}

/// Combines the errors collected while publishing multiple packages into a
/// single error, preserving each error's context chain.
fn combine_publish_errors(mut errors: Vec<AnyError>) -> AnyError {
  if errors.len() == 1 {
    return errors.remove(0);
  }

  let mut message = format!("Failed to publish {} packages:", errors.len());
  for err in &errors {
    // `{:#}` renders the full anyhow context chain (e.g.
    // "Failed to publish @scope/name: <cause>").
    message.push_str(&format!("\n\n* {:#}", err));
  }
  deno_core::anyhow::anyhow!(message)
}

async fn publish_package(
  http_client: &HttpClient,
  package: Rc<PreparedPublishPackage>,
  registry_api_url: &Url,
  registry_url: &Url,
  authorization: &str,
  provenance: bool,
) -> Result<(), AnyError> {
  log::info!(
    "{} @{}/{}@{} ...",
    colors::intense_blue("Publishing"),
    package.scope,
    package.package,
    package.version
  );

View on GitHub (pinned to f7822238ca)