What Causes 'Script error.' in the Console (and What to Do)
Why the browser shows 'Script error.' with no details, how CORS policies hide cross-origin errors, and how to get the real error message.
What Causes “Script error.” in the Console (and What to Do)
You open the console and see this:
Script error.
No file name. No line number. No stack trace. Just two words and a period.
This is the browser’s way of telling you that a JavaScript error occurred in a script loaded from a different origin, and the same-origin policy prevents it from revealing the details. The error is real. The browser just won’t tell you what it was.
Why this happens
Browsers enforce the same-origin policy on error reporting. When a <script> tag loads JavaScript from a different domain (a CDN, a third-party analytics library, an ad script), and that script throws an error, the browser sanitizes the error before passing it to window.onerror. Instead of the actual message, file, and line number, you get "Script error." with zeros for line and column.
This is a security feature. Without it, a malicious page could load scripts from other origins and use error messages to infer information about the response content. For example, an attacker could load a script from a banking site, and the error message might reveal whether the user is logged in based on how the script fails.
The window.onerror handler receives the sanitized version:
window.onerror = function(message, source, lineno, colno, error) {
console.log(message) // "Script error."
console.log(source) // ""
console.log(lineno) // 0
console.log(colno) // 0
console.log(error) // null
}
The window.addEventListener('error', ...) handler has the same limitation for cross-origin scripts. Both APIs get the same sanitized data.
Common causes
1. Scripts loaded from a CDN without CORS headers
You load a library from a CDN using a plain <script> tag. If the CDN does not send Access-Control-Allow-Origin headers, the browser treats the script as an opaque cross-origin resource. Any errors it throws get masked.
<!-- No crossorigin attribute, errors are masked -->
<script src="https://cdn.example.com/library.js"></script>
Fix: Add the crossorigin attribute to the script tag, and make sure the CDN sends Access-Control-Allow-Origin in the response.
<script src="https://cdn.example.com/library.js" crossorigin="anonymous"></script>
The crossorigin="anonymous" attribute tells the browser to make a CORS request for the script. If the server responds with Access-Control-Allow-Origin: * (or your specific origin), the browser will report full error details.
Most major CDNs (cdnjs, jsDelivr, unpkg, Google Hosted Libraries) already send CORS headers. If yours doesn’t, you’ll get a CORS error when loading the script. Switch to a CDN that supports it, or host the script yourself.
2. Third-party scripts you don’t control
Analytics, chat widgets, A/B testing tools, and ad scripts frequently throw errors. Because they load from third-party domains, all you see is "Script error.". You have no control over their server headers.
Fix: Wrap calls to third-party APIs in a try/catch. You can’t fix errors inside the third-party script, but you can catch errors at the boundary where your code interacts with theirs.
try {
thirdPartyWidget.init({ apiKey: 'abc123' })
} catch (err) {
console.error('Widget init failed:', err.message)
// err contains the full error details because you caught it in your origin
}
For errors that happen asynchronously inside the third-party script, there is no reliable way to get the details without the third party adding CORS headers. Contact the vendor if the errors are frequent. Most reputable vendors already serve their scripts with CORS headers for exactly this reason.
3. Scripts served from a different subdomain or port
Even app.example.com loading a script from cdn.example.com counts as a different origin. Same domain, different subdomain. The same-origin policy applies.
<!-- Loaded on app.example.com from cdn.example.com -->
<script src="https://cdn.example.com/bundle.js"></script>
Fix: Same as cause 1. Add crossorigin="anonymous" to the tag and configure your CDN subdomain to send Access-Control-Allow-Origin.
Access-Control-Allow-Origin: https://app.example.com
Or use * if the script is not sensitive:
Access-Control-Allow-Origin: *
During local development, localhost:3000 and localhost:8080 are also different origins. The port matters. Scripts served from your API port will show "Script error." on your dev server’s port unless CORS headers are present.
4. Error reporting services showing “Script error.” in dashboards
If you use an error tracking tool and a large percentage of your errors show as "Script error.", it means your window.onerror handler is capturing the sanitized version. The underlying errors could be anything, from a real bug in a CDN library to a harmless warning in an ad script.
Fix: Audit every <script> tag on the page. For each external script, ensure it has crossorigin="anonymous" and the server sends CORS headers. This will convert most "Script error." entries into real error messages with full stack traces.
Run this in the console to list all external scripts on the page:
document.querySelectorAll('script[src]').forEach((s) => {
const url = new URL(s.src, location.href)
if (url.origin !== location.origin) {
console.log(s.src, 'crossorigin:', s.crossOrigin)
}
})
Any script that prints crossorigin: null is a candidate for masking errors.
Diagnosing the actual error
If you can reproduce the issue, open Chrome DevTools. The Console tab shows the full error even for cross-origin scripts because DevTools has elevated privileges. The "Script error." masking only applies to window.onerror and the error event. DevTools bypasses it entirely.
Steps:
- Open DevTools (F12 or Cmd+Option+I)
- Go to the Console tab
- Enable “Preserve log” so errors aren’t cleared on navigation
- Reproduce the user action that triggers the error
- The full error message, file, and line number will appear
If you cannot reproduce the issue locally, you need the crossorigin attribute fix described above so your error reporting captures the real details in production.
Prevention
Add crossorigin="anonymous" to every external <script> tag by default. There’s no downside when the server supports CORS headers (which most CDNs do), and it ensures you get full error details.
If you use a bundler, configure it to add the attribute automatically:
// Webpack - HtmlWebpackPlugin
new HtmlWebpackPlugin({
scriptLoading: 'defer',
crossOriginLoading: 'anonymous',
})
// Vite adds crossorigin to injected scripts by default.
// For manual script tags in index.html, add it yourself.
For scripts you host yourself, make sure your server or CDN sends Access-Control-Allow-Origin on .js files. Cloudflare, Vercel, and Netlify do this by default for static assets. If you use nginx, add the header explicitly:
location ~* \.js$ {
add_header Access-Control-Allow-Origin * always;
}
For a comprehensive solution, consider a Content Security Policy that limits which origins can serve scripts on your page. This won’t fix "Script error." directly, but it reduces the number of third-party scripts running (and throwing errors) in the first place.
Hushbug detects JavaScript errors including cross-origin script failures automatically while you browse. Coming soon to the Chrome Web Store.