{"record":{"id":"313f5af24611638f","repo":"denoland/deno","slug":"no-packages-to-publish","errorCode":null,"errorMessage":"No packages to publish","messagePattern":"No packages to publish","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/tools/publish/mod.rs","lineNumber":189,"sourceCode":"    ),\n    cli_factory.module_graph_creator().await?.clone(),\n    cli_factory.type_checker().await?.clone(),\n    cli_options.clone(),\n    module_content_provider,\n  );\n\n  let prepared_data = publish_preparer\n    .prepare_packages_for_publishing(\n      publish_flags.allow_slow_types,\n      &diagnostics_collector,\n      publish_configs,\n    )\n    .await?;\n\n  diagnostics_collector.print_and_error()?;\n\n  if prepared_data.package_by_name.is_empty() {\n    bail!(\"No packages to publish\");\n  }\n\n  if std::env::var(\"DENO_TESTING_DISABLE_GIT_CHECK\")\n    .ok()\n    .is_none()\n    && !publish_flags.allow_dirty\n    && let Some(dirty_text) =\n      check_if_git_repo_dirty(cli_options.initial_cwd()).await\n  {\n    log::error!(\"\\nUncommitted changes:\\n\\n{}\\n\", dirty_text);\n    bail!(\n      \"Aborting due to uncommitted changes. Check in source code or run with --allow-dirty\"\n    );\n  }\n\n  if publish_flags.dry_run {\n    for (_, package) in prepared_data.package_by_name {\n      log::info!(","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/cli/tools/publish/mod.rs#L171-L207","documentation":"After building the module graph and preparing tarballs, publish asserts that at least one package survived: `prepared_data.package_by_name` must not be empty. This bail fires when the resolved publish set was empty at preparation time — typically every candidate member was excluded from publishing. Note the separate, earlier path: when every package is filtered out as already published, publish instead prints 'Success - All packages are already published' and exits 0, so this error means nothing was ever eligible.","triggerScenarios":"`deno publish` where no package registers for the publish set: a workspace whose members are all excluded via `\"publish\": false` (and the root config falls through the name/publish/exports checks without bailing), or configs that never become JSR packages (missing name+exports).","commonSituations":"Monorepos that mark members `\"publish\": false` for private packages and later exclude the last publishable member; scaffolding a new package whose deno.json lacks `exports`; running publish after restructuring a workspace.","solutions":["Re-enable publishing for the member you want: remove `\"publish\": false` from its deno.json.","Ensure at least one config has `name`, `version`, and `exports` so it registers as a JSR package.","If everything is intentionally private, don't run `deno publish` — use `deno pack` or a private registry workflow instead."],"exampleFix":"// deno.json (before — nothing publishable)\n{\n  \"workspace\": [\"./packages/a\", \"./packages/b\"],\n  \"publish\": false\n}\n// packages/a/deno.json (after — member opt-in)\n{\n  \"name\": \"@scope/a\",\n  \"version\": \"1.0.0\",\n  \"exports\": \"./mod.ts\"\n}","handlingStrategy":"validation","validationCode":"# fail fast if no workspace config is publishable (name + exports + not publish:false)\nnode -e '\nconst fs = require(\"fs\");\nconst read = (p) => JSON.parse(fs.readFileSync(p, \"utf8\"));\nconst root = read(\"deno.json\");\nconst members = (root.workspace ?? []).map((m) => read(`${m}/deno.json`));\nconst publishable = [root, ...members].some((c) => c.name && c.exports && c.publish !== false);\nif (!publishable) { console.error(\"no publishable packages — nothing to publish\"); process.exit(1); }'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep at least one member with `name` + `version` + `exports` and no `\"publish\": false` when a workspace must be publishable.","Review exclusions after removing or privatizing members.","Use `deno publish --dry-run` locally to confirm the publish set is non-empty before CI."],"tags":["publish","workspace","exclusions","jsr","deno-json"],"backgroundTag":"nothing-to-publish","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}