denoland/deno · error · AnyError

A deno.json file could not be found or created

Error message

A deno.json file could not be found or created

What it means

`deno approve` (lifecycle-scripts permission management) edits the workspace root deno.json. If the start directory has no member deno.json it tries to create one via create_deno_json and re-resolves options; when a root deno.json still cannot be found afterwards, the command fails here — there is no config file to write permissions into.

Solutions

  1. cd into the Deno project that owns the config and re-run
  2. Create a config first: `deno init` or `echo '{}' > deno.json`, then retry
  3. Check the directory is writable and not on a read-only filesystem
  4. Verify any config-path environment overrides point at a real file

Example fix

# before
deno approve scripts   # run outside a project

# after
echo '{}' > deno.json
deno approve scripts
Defensive patterns

Strategy: validation

Validate before calling

async function hasDenoJson(start = Deno.cwd()): Promise<boolean> {
  let d = start;
  while (true) {
    try { await Deno.stat(d + '/deno.json'); return true; }
    catch {
      const parent = d.split('/').slice(0, -1).join('/');
      if (!parent || parent === d) return false;
      d = parent;
    }
  }
}
if (!await hasDenoJson()) {
  throw new Error('no deno.json up the tree; run inside a Deno project');
}

Prevention

When it happens

Trigger: Running `deno approve ...` outside any Deno project: no deno.json discovered up the directory tree, and creation failed or was suppressed (unwritable directory, permissions, package.json-only project), leaving options.workspace().root_deno_json() None.

Common situations: Running the command in the wrong directory; read-only checkouts or mounts in CI; package.json-only Node projects where Deno will not synthesize a deno.json; config-path environment overrides misdirecting discovery.

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/ee74b0cd6299b625. Report an issue: GitHub.

Appendix: source

Thrown at cli/tools/pm/approve_scripts.rs:52

struct ScriptCandidate {
  req: PackageReq,
  specifier: String,
  scripts: Vec<String>,
}

pub async fn approve_scripts(
  flags: Arc<Flags>,
  approve_flags: ApproveScriptsFlags,
) -> Result<(), AnyError> {
  let mut factory = CliFactory::from_flags(flags.clone());
  let mut options = factory.cli_options()?;
  if options.start_dir.member_or_root_deno_json().is_none() {
    factory = create_deno_json(&flags, options)?;
    options = factory.cli_options()?;
  }
  let deno_json = options.workspace().root_deno_json().ok_or_else(|| {
    anyhow::anyhow!("A deno.json file could not be found or created")
  })?;

  let deno_json_path = url_to_file_path(&deno_json.specifier)?;

  let mut config_updater =
    ConfigUpdater::new(ConfigKind::DenoJson, deno_json_path.clone())?;

  let allow_scripts_config = deno_json.to_allow_scripts_config()?;

  let (mut allow_list, mut deny_list) = match allow_scripts_config.allow {
    AllowScriptsValueConfig::All => {
      log::info!(
        "Lifecycle scripts are already allowed for all npm packages in the workspace.",
      );
      return Ok(());
    }
    AllowScriptsValueConfig::Limited(list) => (list, allow_scripts_config.deny),
  };

View on GitHub (pinned to 9ad36f7a2c)