swagger-api/swagger-ui · error · TypeError
wrapSelector needs to return a function that returns a new f
Error message
wrapSelector needs to return a function that returns a new function (ie the wrapped action)
What it means
Plugins extend selectors via statePlugins.<plugin>.wrapSelectors.<selectorName>, and each wrapper must be curried — (originalSelector, getSystem) => (stateSlice, ...args) => newValue — because the system invokes it with the plugin's Immutable state slice (getState().getIn([pluginName])) plus any caller args. This TypeError is raised in getWrappedAndBoundSelectors (src/core/system.js:207) during system construction when the rebuilt selector is not callable. As with wrapActions, a wrapper that forgets the inner arrow more often appears later as a 'TypeError: ... is not a function' at selector invocation.
Source
Thrown at src/core/system.js:207
return objMap(selectorGroups, (selectors, selectorGroupName) => {
let stateName = [selectorGroupName.slice(0, -9)] // selectors = 9 chars
let wrappers = this.system.statePlugins[stateName].wrapSelectors
if(wrappers) {
return objMap(selectors, (selector, selectorName) => {
let wrap = wrappers[selectorName]
if(!wrap) {
return selector
}
if(!Array.isArray(wrap)) {
wrap = [wrap]
}
return wrap.reduce((acc, fn) => {
let wrappedSelector = (...args) => {
return fn(acc, this.getSystem())(getState().getIn(stateName), ...args)
}
if(!isFn(wrappedSelector)) {
throw new TypeError("wrapSelector needs to return a function that returns a new function (ie the wrapped action)")
}
return wrappedSelector
}, selector || Function.prototype)
})
}
return selectors
})
}
getStates(state) {
return Object.keys(this.system.statePlugins).reduce((obj, key) => {
obj[key] = state.get(key)
return obj
}, {})
}
getStateThunks(getState) {
return Object.keys(this.system.statePlugins).reduce((obj, key) => {View on GitHub (pinned to 3d9d0916d4)
Solutions
- Make every wrapSelectors entry a double arrow: (ori, system) => (state, ...args) => { return ori(state, ...args) }.
- Confirm the selector key matches an existing selector in that statePlugin.
- Remember the inner function's first argument is the plugin's Immutable state slice, not the whole Redux store.
Example fix
// before
wrapSelectors: {
isOAS3: (ori, system) => true
}
// after
wrapSelectors: {
isOAS3: (ori, system) => (state, ...args) => {
return ori(state, ...args)
}
} Defensive patterns
Strategy: validation
Validate before calling
// Validate a plugin's wrapSelectors before registering it.
function validateWrapSelectors(plugin) {
const groups = (plugin && plugin.statePlugins) || {}
for (const [pluginName, sp] of Object.entries(groups)) {
for (const [name, wrap] of Object.entries(sp.wrapSelectors || {})) {
const arr = Array.isArray(wrap) ? wrap : [wrap]
arr.forEach((fn, i) => {
if (typeof fn !== "function")
throw new Error(`wrapSelectors[${pluginName}.${name}][${i}] is not a function`)
const produced = fn(() => {}, {}) // (ori, system)
if (typeof produced !== "function")
throw new Error(`wrapSelectors[${pluginName}.${name}][${i}] must return a function; got ${typeof produced}`)
})
}
}
return plugin
} Type guard
// Narrows a wrapSelector entry to the curried (ori, system) => fn form.
const isWrapSelector = (w) => {
const fn = Array.isArray(w) ? w[0] : w
return typeof fn === "function" && typeof fn(() => {}, {}) === "function"
} Try / catch
try {
SwaggerUI({ plugins: [myPlugin], domNode: "#swagger" })
} catch (e) {
if (/wrapSelector needs to return a function/.test(e.message)) {
console.error("A wrapSelectors entry is not curried (needs two arrow functions):", e)
} else {
throw e
}
} Prevention
- Always use the two-arrow shape (ori, system) => (state, ...args) => result for wrapSelectors.
- Remember the inner first argument is the plugin's Immutable state slice, not the full store.
- Model custom wrapSelectors on src/core/plugins/oas31/auth-extensions/wrap-selectors.js.
When it happens
Trigger: Defining wrapSelectors with a single arrow returning a value, e.g. wrapSelectors: { isOAS3: (ori, system) => true } instead of (ori, system) => (state, ...args) => true; returning a non-function from the outer arrow; copying a wrapActions-shaped signature into a wrapSelectors slot; getting the argument order wrong so the outer call yields a value.
Common situations: Writing a plugin that augments auth or spec selectors and flattening the wrapper to one arrow; copying an OAS31 wrapSelector example but dropping one layer; selector key not matching an existing selector name (silently no-ops).
Related errors
- wrapActions needs to return a function that returns a new fu
- Need a string, to fetch a component. Was given a ${typeof co
AI-assisted analysis of swagger-api/swagger-ui@3d9d0916d4 (2026-08-13).
Data as JSON: /api/errors/fd0484a98b403d80.
Report an issue: GitHub.