{"record":{"id":"09547eee899a7174","repo":"remix-run/remix","slug":"optionpath-must-be-a-non-empty-string","errorCode":null,"errorMessage":"${optionPath} must be a non-empty string","messagePattern":"(.+?) must be a non-empty string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/assets/src/lib/target.ts","lineNumber":154,"sourceCode":"    }\n\n    normalizedTarget[key as BrowserTargetName] = normalizeBrowserTargetVersion(\n      value,\n      `${optionPath}.${key}`,\n    )\n  }\n\n  return Object.keys(normalizedTarget).length === 0 ? undefined : normalizedTarget\n}\n\nfunction normalizeScriptTargetVersion(value: unknown, optionPath: string): AssetTarget['es'] {\n  if (typeof value !== 'string') {\n    throw new TypeError(`${optionPath} must be a string`)\n  }\n\n  let normalizedValue = value.trim()\n  if (normalizedValue.length === 0) {\n    throw new TypeError(`${optionPath} must be a non-empty string`)\n  }\n\n  if (!/^\\d+$/.test(normalizedValue)) {\n    throw new TypeError(`${optionPath} must use a single numeric year like \"2020\"`)\n  }\n\n  if (!/^\\d{4}$/.test(normalizedValue) || Number(normalizedValue) < 2015) {\n    throw new TypeError(`${optionPath} must use a four-digit year of 2015 or higher`)\n  }\n\n  return `es${normalizedValue}`\n}\n\nfunction normalizeBrowserTargetVersion(value: unknown, optionPath: string): AssetTargetVersion {\n  if (typeof value !== 'string') {\n    throw new TypeError(`${optionPath} must be a string`)\n  }\n","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/assets/src/lib/target.ts#L136-L172","documentation":"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.","triggerScenarios":"`normalizeTarget({ script: { es: '' } })` or `{ script: { es: '   ' } })`, or a template/env variable that interpolates to an empty string, e.g. `process.env.SCRIPT_TARGET ?? ''`.","commonSituations":"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:`).","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"],"exampleFix":"// before\nlet target = { script: { es: process.env.ES_TARGET ?? '' } }\n// after\nlet target = { script: { es: process.env.ES_TARGET || '2020' } }","handlingStrategy":"validation","validationCode":"for (let [key, value] of Object.entries(targetConfig.script ?? {})) {\n  if (typeof value !== 'string' || value.trim().length === 0) {\n    throw new Error(`target.script.${key} must be a non-empty string`)\n  }\n}","typeGuard":"let isNonEmptyString = (value: unknown): value is string =>\n  typeof value === 'string' && value.trim().length > 0","tryCatchPattern":null,"preventionTips":["Default env-derived versions to a real value: process.env.ES_TARGET || '2020'","Reject blank fields in config forms before submission"],"tags":["config","validation","empty-string"],"backgroundTag":"invalid-config-value","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}