This error occurs when using import.meta.glob with dynamic values or in contexts where Vite cannot statically analyze the glob pattern at build time. The fix is to use string literals directly instead of variables or expressions.
This error appears when you try to use Vite's `import.meta.glob()` function with dynamic values, variables, or in contexts where static analysis fails. Vite extends the global import.meta object with `import.meta.glob`, a special function that allows importing multiple modules from the file system using glob patterns. The key constraint is that `import.meta.glob()` must be statically analyzable at build time. This means Vite's compiler needs to determine exactly which files to include during the build process. When you pass variables, function parameters, or use it in contexts where the pattern cannot be determined statically, Vite cannot perform this analysis and throws this error. This limitation exists because `import.meta.glob()` is transformed at compile time into individual dynamic imports for each matched file. The glob matching happens during the build step, not at runtime, which is why dynamic patterns are not supported.
The most common fix is to replace any variables or expressions with direct string literals:
// ❌ This will not work
const path = './components/**/*.tsx';
const modules = import.meta.glob(path);
// ✅ Use string literals directly
const modules = import.meta.glob('./components/**/*.tsx');If you need different patterns, use multiple calls or combine patterns in an array:
// Multiple patterns
const modules = import.meta.glob([
'./components/**/*.tsx',
'./pages/**/*.tsx'
]);If you're using import.meta.glob in a utility function, move it directly into the component or module where it's needed:
// ❌ Don't wrap in utility functions
function loadModules(pattern) {
return import.meta.glob(pattern); // Error!
}
// ✅ Use directly in your component
function MyComponent() {
const modules = import.meta.glob('./assets/**/*.png');
// Use modules...
}If you need dynamic behavior, perform the filtering/selection after loading all possible modules.
If you see TypeScript errors about glob not existing on ImportMeta, add Vite's types to your tsconfig.json:
{
"compilerOptions": {
"types": ["vite/client"]
}
}This adds the proper type definitions for Vite's import.meta extensions.
Glob patterns must start with / or ./ and cannot reference node_modules packages:
// ❌ Cannot import from node_modules
const langs = import.meta.glob('highlight.js/lib/languages/*.js');
// ✅ Use relative paths for your project files
const components = import.meta.glob('./src/components/**/*.tsx');
// ✅ Absolute from project root
const assets = import.meta.glob('/assets/images/**/*.png');If you need to import from node_modules, use regular imports instead.
By default, import.meta.glob uses lazy loading with dynamic imports. If you need all modules loaded immediately, use the eager option:
// Lazy loading (default) - splits into separate chunks
const modules = import.meta.glob('./components/**/*.tsx');
// Eager loading - imports everything upfront
const modules = import.meta.glob('./components/**/*.tsx', { eager: true });Eager loading can help avoid runtime issues but increases initial bundle size.
You can use query parameters to import files as strings or URLs:
// Import as raw strings
const markdownFiles = import.meta.glob('./posts/**/*.md', {
as: 'raw',
eager: true
});
// Import as URLs (useful for images)
const images = import.meta.glob('./assets/**/*.png', {
as: 'url',
eager: true
});This can be useful when you need file contents rather than module exports.
Build-time vs Runtime:
The fundamental limitation of import.meta.glob is that it's a build-time feature, not a runtime one. Vite's plugin system transforms these calls during bundling into individual import() statements for each matched file. This is why dynamic patterns are impossible—the build tool needs to know the exact file list before the code ever runs.
SSR and Node Modules:
When import.meta.glob appears in code inside node_modules/, Vite does not process it. This can cause issues with SSR frameworks where glob imports might be in framework source code. In these cases, you may need to configure Vite to process those specific dependencies using optimizeDeps.include.
Production vs Development:
Some developers report that glob imports work in development but fail in production. This usually happens because development mode serves files directly from disk, while production builds transform file paths. Always test glob imports in production builds, especially for assets like images.
Pattern Matching:
Vite uses tinyglobby for glob matching. Supported patterns include ** for recursive directories, * for single-level wildcards, and {a,b} for alternatives. Check the tinyglobby documentation for advanced pattern syntax.
Alternative Approaches:
If you truly need dynamic imports based on runtime values, consider:
- Using a static glob to import all possible modules, then filter the results
- Implementing a build-time code generation script that creates the import statements
- Using Vite's import.meta.url with regular dynamic imports for known paths
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite