gatsbyjs/gatsby · error

Loading indicator should never be imported in code that does

Error message

Loading indicator should never be imported in code that doesn't target only browsers

What it means

Thrown at module evaluation time in loading-indicator/indicator.js when `typeof window === 'undefined'`. The loading indicator is a browser-only React component that uses DOM APIs; importing it in a Node/SSR context is a configuration error. Gatsby's build system is supposed to ensure this module only enters browser-targeted bundles.

Source

Thrown at packages/gatsby/cache-dir/loading-indicator/indicator.js:8

import * as React from "react"
import { ShadowPortal } from "../shadow-portal"
import { Style } from "./style"
import { isLoadingIndicatorEnabled } from "$virtual/loading-indicator"
import { debugLog } from "../debug-log"

if (typeof window === `undefined`) {
  throw new Error(
    `Loading indicator should never be imported in code that doesn't target only browsers`
  )
}

if (module.hot) {
  module.hot.accept(`$virtual/loading-indicator`, () => {
    // isLoadingIndicatorEnabled is imported with ES import so no need
    // for dedicated handling as HMR just replace it in that case
  })
}

// HMR can rerun this, so check if it was set before
// we also set it on window and not just in module scope because of HMR resetting
// module scope
if (typeof window.___gatsbyDidShowLoadingIndicatorBefore === `undefined`) {
  window.___gatsbyDidShowLoadingIndicatorBefore = false
}

View on GitHub (pinned to 8b06340921)

Solutions

  1. Remove any custom imports from 'gatsby/cache-dir/loading-indicator' in your own code — these are internal browser-only modules.
  2. Check custom webpack config for server targets that might include browser-only chunks; ensure proper target splitting.
  3. If using SSR/Functions, ensure browser-only components are dynamically imported or guarded by `typeof window !== 'undefined'`.
  4. Update Gatsby to the latest patch version — loading-indicator inclusion is handled by Gatsby's own webpack config.

Example fix

// before — importing browser-only internal module in SSR code
import { LoadingIndicator } from 'gatsby/cache-dir/loading-indicator/indicator'

// after — don't import internal cache-dir modules; use the public API
// The loading indicator is auto-injected by Gatsby in dev mode, no import needed
Defensive patterns

Strategy: type-guard

Validate before calling

// Guard browser-only imports in isomorphic code
if (typeof window !== 'undefined') {
  // safe to import or use browser-only modules here
}

Type guard

// Type-level guard for browser-only modules (concept)
function isBrowser(): boolean {
  return typeof window !== 'undefined'
}

// Only import dynamically in browser context:
if (isBrowser()) {
  import('./browser-only-module').then(mod => mod.useIt())
}

Prevention

When it happens

Trigger: The indicator module is evaluated in a context where window is not defined — typically during SSR (gatsby-node.js, server rendering), or when a custom webpack/server config accidentally includes this browser-only module in a server bundle.

Common situations: Custom webpack configuration that bundles all of Gatsby's cache-dir into a server target, a Gatsby plugin that imports from the cache-dir directly, or a SSR framework (e.g. Gatsby Functions with SSR) that pulls in browser-only modules. Also seen when upgrading Gatsby versions where the loading indicator was newly introduced.

Related errors


AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13). Data as JSON: /api/errors/133be1a0069f887a. Report an issue: GitHub.