denoland/deno · error
esbuild produced no JavaScript output
Error message
esbuild produced no JavaScript output
What it means
The in-memory bundling helper returns the first JavaScript output file it finds (skipping non-JS outputs like CSS and sourcemaps); if none of esbuild's outputs is JS, it bails (cli/tools/bundle/mod.rs:922-938). The entry's graph produced only non-JS artifacts - classically a CSS-only or asset-only entrypoint.
Source
Thrown at cli/tools/bundle/mod.rs:938
)?;
for file in &output_files {
let processed = maybe_process_contents(
file,
should_replace_require_shim(bundle_flags.platform),
bundle_flags.minify,
)?;
if !processed.is_js {
continue;
}
return Ok(
processed
.into_contents()
.unwrap_or_else(|| file.contents.to_vec()),
);
}
deno_core::anyhow::bail!("esbuild produced no JavaScript output")
}
fn metafile_from_response(
response: &BuildResponse,
) -> Result<esbuild_client::Metafile, AnyError> {
Ok(serde_json::from_str::<esbuild_client::Metafile>(
response.metafile.as_deref().ok_or_else(|| {
deno_core::anyhow::anyhow!("expected a metafile to be present")
})?,
)?)
}
async fn bundle_watch(
flags: Arc<Flags>,
bundler: EsbuildBundler,
minified: bool,
platform: BundlePlatform,
output_dir: Option<&Path>,View on GitHub (pinned to 89f33cbef2)
Solutions
- Pass a JS/TS module as the entrypoint - CSS should be imported from JS (import './style.css') rather than bundled as the entry
- Verify the entry file actually contains executable module code and is not empty/type-only
- Check that the correct entry path is being used (typo pointing at a sibling .css/.map file)
Example fix
// before: CSS as entry - no JS output
// run: bundleEntry('src/styles.css') -> esbuild produced no JavaScript output
// after: JS entry that imports the CSS
// src/main.ts: import './styles.css'; export function app() { /* ... */ }
// run: bundleEntry('src/main.ts') Defensive patterns
Strategy: validation
Validate before calling
const JS_ENTRY = /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/i;
function assertJsEntry(entry: string) {
if (!JS_ENTRY.test(entry)) {
throw new Error(`entry must be a JS/TS module, got: ${entry} (import CSS from JS instead)`);
}
} Type guard
function isJsModulePath(path: string): boolean {
return /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/i.test(path);
} Prevention
- Import stylesheets from JS modules rather than bundling CSS directly
- Assert the entry file is non-empty and contains module code before bundling
When it happens
Trigger: Bundling an entry whose outputs are all CSS/maps (e.g. a stylesheet passed where a JS/TS module is expected); a module graph that tree-shakes to zero JS; outputs filtered out because maybe_process_contents marks them non-JS.
Common situations: Build scripts passing style.css or an HTML/CSS asset as the entry to a flow that expects JS bytes; renaming entries such that the real JS entry is no longer passed.
Related errors
- could not get fetch esbuild binary; download it manually and
- failed to locate output for HTML entry '{}'; {js_entry_name}
- bundling failed
- esbuild exited before the rebuild completed
- The bench function must have a name
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/6c89c081eaadbbff.
Report an issue: GitHub.