denoland/deno · error · AnyError
is missing 'version' field
Error message
{} is missing 'version' field What it means
Every package published to JSR must carry a version, so `deno publish` reads `version` from the member's deno.json (`deno_json.json.version`) during preparation and refuses to continue when the field is absent. The message names the exact config file specifier that is missing the field. This is checked per workspace member, so one member without a version fails the whole publish.
Solutions
- Open the deno.json named in the error and add a valid semver version, e.g. `"version": "1.0.0"`.
- In a workspace, reuse the root version with `"version": "workspace:..."` so members stay in sync with the root's `version` field.
- Ensure the version is a plain semver string (no 'v' prefix, no range operators) — JSR rejects those at upload anyway.
- Re-run `deno publish --dry-run` to confirm the member now passes preparation.
Example fix
// before (member deno.json)
{
"name": "@scope/util",
"exports": "./mod.ts"
}
// after
{
"name": "@scope/util",
"version": "workspace:...",
"exports": "./mod.ts"
} Defensive patterns
Strategy: validation
Validate before calling
import { readManifest } from './deps.ts';
const denoJson = JSON.parse(await Deno.readText(memberDenoJsonPath));
if (!denoJson.version && denoJson.version !== 'workspace:...') {
throw new Error(`${memberDenoJsonPath} is missing 'version' field`);
} Type guard
function isPublishableManifest(
m: Record<string, unknown>,
): boolean {
return typeof m.name === 'string' &&
(typeof m.version === 'string' || m.version === 'workspace:...');
} Try / catch
try {
await runDeno(['publish']);
} catch (e) {
if (String(e.message).includes("missing 'version' field")) {
// add "version" to the deno.json named in the message, then re-run
}
} Prevention
- Scaffold new workspace members from a template that includes version.
- In workspaces, use `"version": "workspace:..."` in members to inherit the root version.
- Validate all member deno.json files in a pre-publish CI check.
When it happens
Trigger: A workspace member deno.json that declares `name`, `exports`, but no `version`; converting a private workspace package (never published, no version needed) into a publishable one without adding the field; publishing a single-package repo whose deno.json only has name/imports.
Common situations: Workspaces where the root deno.json has a version and the author assumes members inherit it (for deno.json members you must declare `"version": "workspace:..."` or a literal); scaffolding a new member by copying a template that omitted version; YAML/JSON typo like `Version` (fields are case-sensitive).
Related errors
- Couldn't find a deno.json, deno.jsonc, jsr.json or…
- missing version in package.json of npm package
- No packages to publish
- You did not specify an entrypoint in
- Cannot represent compiler option
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/a889d8d4f818fbab.
Report an issue: GitHub.
Appendix: source
Thrown at cli/tools/publish/mod.rs:523
);
}
}
Ok(diagnostics_by_folder.into_graph())
}
}
}
async fn prepare_publish(
&self,
package: &JsrPackageConfig,
graph: Arc<deno_graph::ModuleGraph>,
diagnostics_collector: &PublishDiagnosticsCollector,
) -> Result<Rc<PreparedPublishPackage>, AnyError> {
let deno_json = &package.config_file;
let config_path = deno_json.specifier.to_file_path().unwrap();
let root_dir = config_path.parent().unwrap().to_path_buf();
let version = deno_json.json.version.clone().ok_or_else(|| {
deno_core::anyhow::anyhow!(
"{} is missing 'version' field",
deno_json.specifier
)
})?;
let (scope, name_no_scope) = registry::parse_package_name(&package.name)?;
let file_patterns = package.member_dir.to_publish_config()?.files;
let tarball = deno_core::unsync::spawn_blocking({
let diagnostics_collector = diagnostics_collector.clone();
let module_content_provider = self.module_content_provider.clone();
let cli_options = self.cli_options.clone();
let config_path = config_path.clone();
let config_url = deno_json.specifier.clone();
let has_license_field = package.license.is_some();
let current_package_name = package.name.clone();
move || {
let root_specifier =
ModuleSpecifier::from_directory_path(&root_dir).unwrap();View on GitHub (pinned to f7822238ca)