twbs/bootstrap · error · TypeError

: Option " " provided type " " but expected type " ".

Error message

${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".

What it means

Whenever a component is constructed or reconfigured, Config._typeCheckConfig (util/config.js:51) walks the component's DefaultType table and regex-tests each option value's runtime type against expectations like 'number', 'boolean' or '(string|element|function)'. A failed test throws a TypeError naming the component, the option, the actual type and the expected type. Values read from data-bs-* attributes are auto-coerced (numeric strings to number, 'true' to boolean, JSON to object), but values passed programmatically in the config object are checked exactly as given.

Solutions

  1. Pass native types in the JS config: interval: 5000 (number), keyboard: false (boolean).
  2. Read the error message — it names the exact option and the expected type, mirroring the component's DefaultType table.
  3. Convert string sources before init: Number(value) for numeric options, value === 'true' for booleans.
  4. Fix and re-init: dispose the bad instance or call getOrCreateInstance again with corrected config.

Example fix

// before
new bootstrap.Carousel(el, { interval: '5000' })
// CAROUSEL: Option "interval" provided type "string" but expected type "number".

// after
new bootstrap.Carousel(el, { interval: 5000 })
Defensive patterns

Strategy: validation

Validate before calling

function configProblems(Component, config) {
  const problems = []
  for (const [key, expected] of Object.entries(Component.DefaultType)) {
    const value = config[key]
    if (value === undefined) continue
    const actual = value === null ? 'null'
      : value instanceof Element ? 'element'
      : Array.isArray(value) ? 'array'
      : typeof value
    if (!new RegExp(expected).test(actual)) {
      problems.push(`${Component.NAME}: "${key}" expected ${expected}, got ${actual}`)
    }
  }
  return problems
}

const problems = configProblems(bootstrap.Carousel, { interval: '5000' })
if (problems.length) console.warn(problems.join('\n')) // fix before constructing

Type guard

function typedConfig<T extends object>(config: T): T {
  // compile-time counterpart: declare option types to mirror DefaultType
  // (e.g. { interval: number; keyboard: boolean }) so strings fail at build time
  return config
}

Try / catch

try {
  return new bootstrap.Modal(el, userConfig)
} catch (err) {
  if (err instanceof TypeError && /Option ".*" provided type/.test(err.message)) {
    reportConfigError(err.message) // surface the exact option/type pair to the caller
    return null
  }
  throw err
}

Prevention

When it happens

Trigger: new bootstrap.Carousel(el, { interval: '5000' }) — string where DefaultType says 'number'; new bootstrap.Modal(el, { keyboard: 'false' }) — string instead of boolean; new bootstrap.Toast(el, { delay: '3000' }); a wrapper passing everything as strings from a form or dataset.

Common situations: Config objects assembled from strings (URL/query params, form fields, data attributes read via el.dataset which returns strings); framework wrappers with loose prop types; data-bs-* values that cannot auto-coerce (e.g. data-bs-delay="fast").

Related errors


AI-assisted analysis of twbs/bootstrap@6177d5f849 (2026-08-22). Data as JSON: /api/errors/926504b6f337674a. Report an issue: GitHub.

Appendix: source

Thrown at js/src/util/config.js:57

  _mergeConfigObj(config, element) {
    const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {} // try to parse

    return {
      ...this.constructor.Default,
      ...(typeof jsonConfig === 'object' ? jsonConfig : {}),
      ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),
      ...(typeof config === 'object' ? config : {})
    }
  }

  _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {
    for (const [property, expectedTypes] of Object.entries(configTypes)) {
      const value = config[property]
      const valueType = isElement(value) ? 'element' : toType(value)

      if (!new RegExp(expectedTypes).test(valueType)) {
        throw new TypeError(
          `${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`
        )
      }
    }
  }
}

export default Config

View on GitHub (pinned to 6177d5f849)