Diagnosing Missing Externs in ClojureScript Advanced Builds
A step‑by‑step diagnostic guide for fixing missing externs in ClojureScript :advanced builds, with checks, fixes, and verification steps.
06 Sept 2026, 18:28 UTC

Recognizable condition
When you run a ClojureScript build with :optimizations :advanced you see one or more of the following:
- Warnings such as "JS parsing failed" or "Unknown externs" during compilation.
- The generated JavaScript file is noticeably larger than expected (dead‑code elimination not working).
- At runtime you get errors like "undefined is not a function" or "Cannot read property X of undefined" when calling a JavaScript library (e.g., React, lodash).
Cause / diagnostic table
| Possible cause | What to look for |
|---|---|
| Externs missing for a used JS library | Library appears in :foreign-libs or npm dependencies but no externs file is listed under :externs. |
| Stale compiler cache | Build succeeds after a clean but fails again without changing sources. |
| Incorrect externs content | Externs file exists but property names differ from those actually used in the code. |
Ordered checks
- Verify build profile
Open
project.clj(Leiningen) ordeps.edn(tools.deps) and confirm that the build you are running uses:optimizations :advanced. - Inspect externs configuration
Look for a vector under the key
:externs. It should contain paths to externs files (e.g.,"externs/react.js"). If the key is absent or empty, externs are not being supplied. - Check library inclusion method
Determine whether the JavaScript library is brought in via
:foreign-libs, an npm dependency (:npm-depsin shadow-cljs), or a plain:js-moduleimport. Note the exact name used in your ClojureScript code (e.g.,js/React). - Run a whitespace build
Execute the same build with
:optimizations :none(or:whitespace) to see if the code works without advanced optimizations. Success here indicates the problem is externs‑related rather than a syntax error. - Inspect the externs file content
If an externs file is present, open it and verify that the property names you reference (e.g.,
render,createElement) appear exactly as they are used, including case.
Fixes tied to findings
- Missing externs entry
Add the appropriate externs file to the
:externsvector. For a library installed via npm, you can generate externs withgexterns:# Install gexterns if needed npm install -g gexterns # Generate externs for React (adjust version as needed) gexterns react@18 > resources/public/externs/react.jsThen update your build config:
:externs ["resources/public/externs/react.js"] - Stale cache
Delete the target directory before rebuilding:
rm -rf target # Leiningen rm -rf .shadow-cljs # shadow-cljsThen run the build again.
- Incorrect externs
Either regenerate the externs with the exact library version you depend on, or manually edit the file to match the used property names. After editing, run the advanced build and check that the warnings disappear.
- Work‑around for development
If you only need to get a build running quickly, switch to
:optimizations :noneor:whitespace. Remember that this disables dead‑code elimination and will increase the output size.
Escalation criteria
Proceed to the following steps if the above checks and fixes do not resolve the issue:
- Confirm that the externs file is being read by the compiler: add a temporary line like
// @externsat the top of the file and look for a compiler warning about an unknown externs directive. - Clean the compiler cache (
:target-diror.shadow-cljs) and rebuild. - If the problem persists, file an issue with the library’s externs generator (e.g., the
gexternsrepository) providing: - The exact version of the JavaScript library.
- The externs file you are using.
- A minimal ClojureScript snippet that reproduces the missing‑externs warning.
Verification
After applying a fix, run the advanced build again and:
- Ensure no "Unknown externs" or "JS parsing failed" warnings appear.
- Load the compiled JavaScript in a browser or Node and verify that library calls (e.g.,
js/React.render) execute without runtime "undefined is not a function" errors. - Optionally, compare the gzipped size of the output before and after adding externs; a successful externs setup should yield a smaller file due to proper dead‑code elimination.
Diagram labels
Illustrative symbols for the diagnostic flow:
- Missing externs warning
- Large output JS
- Runtime undefined error
- Successful advanced build
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.