denoland/deno · error · AnyError
Missing name
Error message
Missing name
What it means
`deno pack` derives the default tarball filename as `<name>-<version>.tgz` from deno.json's `name` field (default_tarball_filename is the single place this is computed). A config without `name` leaves nothing to derive the filename from, so pack fails before writing anything.
Solutions
- Add `"name"` and `"version"` to deno.json: `"name": "my-pkg", "version": "1.0.0"`
- For scoped packages use `"name": "@scope/my-pkg"` (normalized to scope-my-pkg)
- Run pack from the workspace member whose config actually defines the package
Example fix
// before (deno.json)
{ "tasks": { "dev": "deno run main.ts" } }
// after
{
"name": "@scope/my-pkg",
"version": "1.0.0",
"tasks": { "dev": "deno run main.ts" }
} Defensive patterns
Strategy: validation
Validate before calling
const config = JSON.parse(await Deno.readText('deno.json'));
if (typeof config.name !== 'string' || config.name.length === 0) {
throw new Error('deno.json needs a "name" before deno pack');
} Type guard
interface NamedConfig { name: string; version: string }
const isNamedConfig = (c: unknown): c is NamedConfig =>
!!c && typeof (c as any).name === 'string' &&
typeof (c as any).version === 'string'; Prevention
- Add name/version as soon as a project might ever be packed
- Validate config fields in pre-pack CI steps
- Keep publish metadata in the member config, not only the workspace root
When it happens
Trigger: Running `deno pack` where deno.json has no `name` entry — e.g. a workspace root config that only holds tasks and imports, or a script project created by `deno init` without publish metadata.
Common situations: Workspace root configs used purely for task definitions; name/version defined only in a member config while running pack at the root; hand-rolled configs missing publish fields.
Related errors
- Missing name in config
- Git repository has uncommitted changes. Use --allow-dirty…
- Invalid package name
- Missing 'exports' field in
- Missing 'name' field in
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/ea0425e3fafd738b.
Report an issue: GitHub.
Appendix: source
Thrown at cli/tools/pack/npm_tarball.rs:27
use super::AssetFile;
use super::ProcessedFile;
use super::ReadmeOrLicense;
use super::extensions::js_to_dts_extension;
/// Compute the default tarball filename (`scope-name-version.tgz`) that
/// `pack` writes when no `--output` is given. Extracted so the asset
/// collector can exclude this exact path (instead of guessing by `.tgz`
/// extension) and so the name is computed in exactly one place.
pub fn default_tarball_filename(
config_file: &ConfigFile,
version: &str,
) -> Result<PathBuf, AnyError> {
let name = config_file
.json
.name
.as_ref()
.ok_or_else(|| deno_core::anyhow::anyhow!("Missing name"))?;
// Convert @scope/name to scope-name
let normalized = name.replace('@', "").replace('/', "-");
// The package name shape is checked against `@scope/name` higher up
// (see `pack` in mod.rs), but that check is loose — it does not
// forbid path-traversal sequences. Treat this as a hard safety
// boundary right before we open a file, rejecting any derived
// tarball name that contains `..` or path separators so we never
// escape the cwd regardless of upstream validation drift.
if normalized.contains("..") || normalized.contains('/') {
return Err(deno_core::anyhow::anyhow!(
"refusing to write tarball with unsafe name derived from package: {}",
name
));
}
Ok(PathBuf::from(format!("{}-{}.tgz", normalized, version)))
}
/// Tar archive paths must use forward slashes, even on Windows. Output pathsView on GitHub (pinned to 9ad36f7a2c)