denoland/deno · error · AnyError
Cannot generate declarations for files with different…
Error message
Cannot generate declarations for files with different compiler option scopes.
'{}' uses scope '{}' but '{}' uses scope '{}'.
Separate these files into different invocations. What it means
Thrown by `deno cache` / declaration emit when the set of root files being type-checked in a single TSC pass do not all resolve to the same compiler-options scope. Deno maps every specifier to a compiler options entry (keyed by the effective tsconfig/deno.json settings that cover it, e.g. a workspace member's own compilerOptions). Because TSC type-checks all root names in one invocation, mixing scopes would produce wrong declarations, so Deno refuses and asks you to split the invocation.
Solutions
- Split the work: run a separate `deno cache` (or emit) invocation per scope, e.g. one per workspace member, so each invocation's root names share one scope.
- Align the scopes: make the conflicting deno.json / workspace-member `compilerOptions` identical (or delete the per-member override) so both files resolve to the same key.
- Identify the two scopes named in the message (first file's scope vs the offending file's scope) and move the offending file under the config that owns the first entrypoint.
- If you do not need declarations for the second file, drop it from the same invocation instead of mixing it in.
Example fix
# before: one invocation, two scopes deno cache --config memberA/deno.json memberA/mod.ts memberB/mod.ts # error: 'memberA/mod.ts' uses scope '...memberA/deno.json' but 'memberB/mod.ts' uses scope '...memberB/deno.json' # after: one invocation per scope deno cache --config memberA/deno.json memberA/mod.ts deno cache --config memberB/deno.json memberB/mod.ts
Defensive patterns
Strategy: validation
Validate before calling
# group entrypoints by their deno.json/tsconfig scope before caching # (each workspace member gets its own invocation) for member in memberA memberB; do deno cache --config "$member/deno.json" "$member"/*.ts done
Try / catch
deno cache main.ts 2>&1 | grep -q "different compiler option scopes" && { echo "split into per-scope invocations"; exit 1; } Prevention
- One `deno cache`/emit invocation per workspace member or per tsconfig scope.
- Keep compilerOptions consistent across workspace members unless a split is intended.
- When adding a second entrypoint, confirm it is covered by the same deno.json as the first.
- Read the two scope keys in the message — they name exactly which configs conflict.
When it happens
Trigger: Running one command that emits declarations for multiple entrypoints where at least one file is covered by a different deno.json/tsconfig scope: e.g. a Deno workspace whose members declare differing `compilerOptions`, or entrypoints that resolve through node_modules/JSR packages carrying their own settings. The loop at cli/tools/transpile.rs compares each root_name's `entry_for_specifier()` key against the first file's key and bails on the first mismatch.
Common situations: Adopting Deno workspaces with per-member tsconfig overrides; adding a second entrypoint (test file, bench file) that sits in another workspace member; refactoring a monorepo so one import crosses a compilerOptions boundary; Deno version upgrades that changed how scopes are keyed.
Related errors
- Type checking failed
- Entry point must be a file
- Error getting navigation tree for
- native tsc exited with
- No declaration file emitted for entry point
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/642700600bb69858.
Report an issue: GitHub.
Appendix: source
Thrown at cli/tools/transpile.rs:278
specifiers,
crate::graph_util::BuildGraphWithNpmOptions {
is_dynamic: false,
loader: None,
npm_caching: cli_options.default_npm_caching_strategy(),
},
)
.await?;
// Validate that all files share the same compiler options scope, since
// TSC type-checks all files in a single pass.
let compiler_options_resolver = factory.compiler_options_resolver()?;
let first_specifier = &root_names[0].0;
let (first_key, _) =
compiler_options_resolver.entry_for_specifier(first_specifier);
for (specifier, _) in root_names.iter().skip(1) {
let (key, _) = compiler_options_resolver.entry_for_specifier(specifier);
if key != first_key {
anyhow::bail!(
"Cannot generate declarations for files with different compiler option scopes.\n\
'{}' uses scope '{}' but '{}' uses scope '{}'.\n\
Separate these files into different invocations.",
first_specifier,
first_key,
specifier,
key,
);
}
}
let type_checker = factory.type_checker().await?;
let result = type_checker.emit_declarations(
Arc::new(graph),
root_names,
cli_options.ts_type_lib_window(),
)?;
View on GitHub (pinned to 9ad36f7a2c)