remix-run/remix · error · TypeError
${optionPath} must be a non-empty string
Error message
${optionPath} must be a non-empty string What it means
Thrown when a script target version string is empty or only whitespace. After confirming the value is a string, the assets normalizer trims it and requires at least one character, because an empty version cannot be mapped to an ES year like es2020.
Source
Thrown at packages/assets/src/lib/target.ts:154
}
normalizedTarget[key as BrowserTargetName] = normalizeBrowserTargetVersion(
value,
`${optionPath}.${key}`,
)
}
return Object.keys(normalizedTarget).length === 0 ? undefined : normalizedTarget
}
function normalizeScriptTargetVersion(value: unknown, optionPath: string): AssetTarget['es'] {
if (typeof value !== 'string') {
throw new TypeError(`${optionPath} must be a string`)
}
let normalizedValue = value.trim()
if (normalizedValue.length === 0) {
throw new TypeError(`${optionPath} must be a non-empty string`)
}
if (!/^\d+$/.test(normalizedValue)) {
throw new TypeError(`${optionPath} must use a single numeric year like "2020"`)
}
if (!/^\d{4}$/.test(normalizedValue) || Number(normalizedValue) < 2015) {
throw new TypeError(`${optionPath} must use a four-digit year of 2015 or higher`)
}
return `es${normalizedValue}`
}
function normalizeBrowserTargetVersion(value: unknown, optionPath: string): AssetTargetVersion {
if (typeof value !== 'string') {
throw new TypeError(`${optionPath} must be a string`)
}
View on GitHub (pinned to 9696913134)
Solutions
- Provide a real year such as '2020' for the script target
- If the value comes from an env var, check it is set and non-empty before passing it (e.g. `process.env.SCRIPT_TARGET || '2020'`)
- Trim/validate user-supplied config before handing it to the assets API
Example fix
// before
let target = { script: { es: process.env.ES_TARGET ?? '' } }
// after
let target = { script: { es: process.env.ES_TARGET || '2020' } } Defensive patterns
Strategy: validation
Validate before calling
for (let [key, value] of Object.entries(targetConfig.script ?? {})) {
if (typeof value !== 'string' || value.trim().length === 0) {
throw new Error(`target.script.${key} must be a non-empty string`)
}
} Type guard
let isNonEmptyString = (value: unknown): value is string => typeof value === 'string' && value.trim().length > 0
Prevention
- Default env-derived versions to a real value: process.env.ES_TARGET || '2020'
- Reject blank fields in config forms before submission
When it happens
Trigger: `normalizeTarget({ script: { es: '' } })` or `{ script: { es: ' ' } })`, or a template/env variable that interpolates to an empty string, e.g. `process.env.SCRIPT_TARGET ?? ''`.
Common situations: Env vars that are unset produce empty strings via `|| ''` or default interpolation; user-facing config forms submitted blank; YAML configs with an empty value (`es:`).
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- basePath must be a string
- fingerprint.buildId must be a string
- fingerprint.buildId must be a non-empty string
- files.extensions must be an array
- files.extensions values must be strings
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/09547eee899a7174.
Report an issue: GitHub.