denoland/deno · error · AnyError

Could not load or create deno.json

Error message

Could not load or create deno.json

What it means

`deno link` records entries in deno.json's `links` field, so it forces config creation by telling the config loader that jsr specifiers are present (which materializes a deno.json when none is found). If load_configs still returns no deno config after that, linking cannot proceed and this error fires.

Solutions

  1. Create deno.json yourself first: `deno init` or `echo '{}' > deno.json`, then run `deno link`
  2. Confirm the current directory is writable and is where you want the config
  3. Fix or remove config-path overrides that misdirect discovery

Example fix

# before
deno link ../shared   # no deno.json anywhere

# after
echo '{}' > deno.json
deno link ../shared
Defensive patterns

Strategy: validation

Validate before calling

try {
  await Deno.stat('deno.json');
} catch {
  throw new Error('deno.json not found; create one (deno init) before deno link');
}

Prevention

When it happens

Trigger: `deno link <path>` from a directory where the config loader can neither find nor create deno.json — package.json-only projects where creation is suppressed, an unwritable cwd, or discovery misdirected by config-path overrides — so deno_config stays None at cli/tools/pm/mod.rs:1443.

Common situations: Node-style projects without any deno.json; read-only directories or container mounts; running link in a scratch directory intending to configure later; a bad DENO_CONFIG_PATH-style override pointing somewhere unusable.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


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

Appendix: source

Thrown at cli/tools/pm/mod.rs:1443

    candidate.to_path_buf()
  } else {
    cwd.join(candidate)
  };
  deno_path_util::normalize_path(std::borrow::Cow::Owned(abs)).into_owned()
}

fn load_deno_config_for_link(
  flags: &Arc<Flags>,
  create_if_missing: bool,
) -> Result<(CliFactory, ConfigUpdater), AnyError> {
  if create_if_missing {
    // For `link`, force creation of deno.json if missing; the `"links"` field
    // lives there. We achieve this by claiming jsr specifiers are present,
    // which makes `load_configs` materialise a deno.json when one isn't found.
    let (cli_factory, _force_package_json, _npm_config, deno_config) =
      load_configs(flags, || true, false, false)?;
    let deno_config = deno_config.ok_or_else(|| {
      deno_core::anyhow::anyhow!("Could not load or create deno.json")
    })?;
    return Ok((cli_factory, deno_config));
  }

  // For `unlink`, never create a deno.json: if there isn't one, there's
  // nothing to unlink. Load only an existing config so a failed unlink can't
  // leave an empty deno.json behind.
  let cli_factory = CliFactory::from_flags(flags.clone());
  let options = cli_factory.cli_options()?;
  let deno_config = match options.start_dir.member_deno_json() {
    Some(deno_json) => ConfigUpdater::new(
      ConfigKind::DenoJson,
      url_to_file_path(&deno_json.specifier)?,
    )?,
    None => bail!("No deno.json found; there are no linked packages to unlink"),
  };
  Ok((cli_factory, deno_config))
}

View on GitHub (pinned to 9ad36f7a2c)