parcel-bundler/parcel · error · Error
use server-entry must be imported in a server environment
Error message
use server-entry must be imported in a server environment
What it means
Thrown when a JS asset contains the React Server Components directive `'use server-entry'` but the asset's environment is not a server environment (asset.env.isServer() === false). The directive marks a module as the client entry bootstrap from a server bundle; running it in a browser/service-worker/worklet target is invalid. The transformer enforces this before setting bundleBehavior = 'isolated'.
Source
Thrown at packages/transformers/js/src/JSTransformer.js:801
} else if (
!asset.env.isServer() &&
!asset.env.isLibrary &&
directives.includes('use server')
) {
asset.setEnvironment({
context: 'react-server',
sourceType: 'module',
outputFormat: 'commonjs',
engines: asset.env.engines,
includeNodeModules: true,
isLibrary: false,
sourceMap: asset.env.sourceMap,
shouldOptimize: asset.env.shouldOptimize,
shouldScopeHoist: asset.env.shouldScopeHoist,
});
} else if (directives.includes('use server-entry')) {
if (!asset.env.isServer()) {
throw new Error(
'use server-entry must be imported in a server environment',
);
}
asset.bundleBehavior = 'isolated';
}
// Server actions must always be wrapped so they can be parcelRequired.
if (directives.includes('use server')) {
asset.meta.shouldWrap = true;
}
for (let dep of dependencies) {
if (dep.kind === 'WebWorker') {
// Use native ES module output if the worker was created with `type: 'module'` and all targets
// support native module workers. Only do this if parent asset output format is also esmodule so that
// assets can be shared between workers and the main thread in the global output format.
let outputFormat;
if (View on GitHub (pinned to 59484858a1)
Solutions
- Move the 'use server-entry' directive into a file that is only reachable from the server entry.
- If the same code path is needed on the client, split it: keep 'use server-entry' on the server module and import a separate client-safe module from the browser bundle.
- Audit `addURLDependency`/`addDependency` calls and target env overrides that may have flipped context.
- Check your targets in package.json: the entry that uses 'use server-entry' must have a server context.
Example fix
// before: src/entry.js used by both server and client
'use server-entry';
import {App} from './App';
// after: split into two files
// src/entry.server.js
'use server-entry';
import {App} from './App';
// src/entry.client.js (no directive)
import {App} from './App'; Defensive patterns
Strategy: validation
Validate before calling
// Ensure 'use server-entry' files are only reachable from server entries
const path = require('path');
function assertServerOnly(filePath, serverEntryDirs) {
const rel = path.relative(process.cwd(), filePath);
if (!serverEntryDirs.some(d => rel.startsWith(d))) {
throw new Error(`file ${filePath} uses 'use server-entry' but is outside server entry dirs ${serverEntryDirs}`);
}
} Prevention
- Keep server entry files in a dedicated directory (e.g. src/server/) and never import them from browser code.
- Use Parcel's environment conditions to branch imports rather than sharing the directive-tagged file.
When it happens
Trigger: A module whose top-level directive list includes 'use server-entry' is resolved into a bundle whose env.context is not server (browser, web-worker, service-worker, worklet). Typical when the same file is imported from both server and client code without an env boundary, or a target mislabels the context.
Common situations: Sharing a single 'use server-entry' file between client and server entry points; a misplaced directive in a file imported by a browser bundle; an env override (e.g. in a URL/dep) that switched context away from 'react-server'/'node'.
Related errors
AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13).
Data as JSON: /api/errors/345d4346836e25ce.
Report an issue: GitHub.