{"id":"5c553f53afb1fab9","repo":"babel/babel","slug":"msg-loc-must-be-a-string-an-array-of-strings","errorCode":null,"errorMessage":"${msg(loc)} must be a string, an array of strings or an object","messagePattern":"(.+?) must be a string, an array of strings or an object","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/babel-core/src/config/validation/option-assertions.ts","lineNumber":402,"sourceCode":"function assertPluginTarget(loc: GeneralPath, value: unknown): PluginTarget {\n  if (\n    (typeof value !== \"object\" || !value) &&\n    typeof value !== \"string\" &&\n    typeof value !== \"function\"\n  ) {\n    throw new Error(`${msg(loc)} must be a string, object, function`);\n  }\n  return value as PluginTarget;\n}\n\nexport function assertTargets(\n  loc: GeneralPath,\n  value: any,\n): TargetsListOrObject {\n  if (isBrowsersQueryValid(value)) return value;\n\n  if (typeof value !== \"object\" || !value || Array.isArray(value)) {\n    throw new Error(\n      `${msg(loc)} must be a string, an array of strings or an object`,\n    );\n  }\n\n  const browsersLoc = access(loc, \"browsers\");\n  const esmodulesLoc = access(loc, \"esmodules\");\n\n  assertBrowsersList(browsersLoc, value.browsers);\n  assertBoolean(esmodulesLoc, value.esmodules);\n\n  for (const key of Object.keys(value)) {\n    const val = value[key];\n    const subLoc = access(loc, key);\n\n    if (key === \"esmodules\") assertBoolean(subLoc, val);\n    else if (key === \"browsers\") assertBrowsersList(subLoc, val);\n    else if (!Object.hasOwn(TargetNames, key)) {\n      const validTargets = Object.keys(TargetNames).join(\", \");","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/babel/babel/blob/06b6eae39da4ce0689fad64e2c48a6375a464208/packages/babel-core/src/config/validation/option-assertions.ts#L384-L420","documentation":"Thrown by assertTargets when the 'targets' option is neither a browserslist query string (e.g. '> 0.25%'), an array of such strings, nor a plain object keyed by target names. Numbers, booleans, nested arrays, or non-browserslist values are rejected.","triggerScenarios":"targets: 90; targets: true; targets: [['chrome', 80]] (nested array); targets: 'last 2 versions' is fine, but targets: { chrome: 'latest' } shape errors later (see 78). Here the top-level type itself is wrong.","commonSituations":"Passing a numeric browser version as the whole targets value; migrating from browserslist config expecting a different shape; JSON configs that wrap targets in an extra array.","solutions":["Use a browserslist query string: targets: '> 0.25%, not dead'.","Use an array of queries: targets: ['> 1%', 'last 2 versions'].","Use an object keyed by target: targets: { chrome: 80, firefox: 78 }."],"exampleFix":"// before\n{ targets: 90 }\n// after\n{ targets: { chrome: 90 } }","handlingStrategy":"type-guard","validationCode":"function isTargetsShape(v) {\n  if (typeof v === 'string') return true;\n  if (Array.isArray(v)) return v.every((x) => typeof x === 'string');\n  if (typeof v === 'object' && v !== null) return true;\n  return false;\n}\nif (opts.targets !== undefined && !isTargetsShape(opts.targets)) {\n  throw new Error('targets must be string, array of strings, or object');\n}","typeGuard":"function isTargetsShape(\n  v: unknown,\n): v is string | string[] | Record<string, unknown> {\n  if (typeof v === 'string') return true;\n  if (Array.isArray(v)) return v.every((x) => typeof x === 'string');\n  return typeof v === 'object' && v !== null;\n}","tryCatchPattern":"try {\n  babel.loadOptions(opts);\n} catch (e) {\n  if (e instanceof Error && /must be a string, an array of strings or an object/.test(e.message)) {\n    opts.targets = undefined; // fall back to .browserslistrc\n    return babel.loadOptions(opts);\n  }\n  throw e;\n}","preventionTips":["Use a browserslist query string for broad targets.","Use an object for per-browser version pins.","Defer to .browserslistrc by omitting targets."],"tags":["config","targets","browserslist","input-validation"],"analyzedSha":"06b6eae39da4ce0689fad64e2c48a6375a464208","analyzedAt":"2026-08-03T20:13:43.465Z","schemaVersion":2}