badges/shields · error · ValidationError
Field `links` must be an array of strings
Error message
Field `links` must be an array of strings
What it means
When the optional `links` field is provided it must be an array. _validate checks Array.isArray(format.links) (badge-maker/lib/index.js:26) and throws this ValidationError if links is a string, object, or any non-array value. This is the not-an-array branch of the links validation.
Source
Thrown at badge-maker/lib/index.js:27
function _validate(format) {
if (format !== Object(format)) {
throw new ValidationError('makeBadge takes an argument of type object')
}
if (!('message' in format)) {
throw new ValidationError('Field `message` is required')
}
const stringFields = ['labelColor', 'color', 'message', 'label', 'logoBase64']
stringFields.forEach(function (field) {
if (field in format && typeof format[field] !== 'string') {
throw new ValidationError(`Field \`${field}\` must be of type string`)
}
})
if ('links' in format) {
if (!Array.isArray(format.links)) {
throw new ValidationError('Field `links` must be an array of strings')
} else {
if (format.links.length > 2) {
throw new ValidationError(
'Field `links` must not have more than 2 elements',
)
}
format.links.forEach(function (field) {
if (typeof field !== 'string') {
throw new ValidationError('Field `links` must be an array of strings')
}
})
}
}
const styleValues = [
'plastic',
'flat',
'flat-square',View on GitHub (pinned to 766fd8bc89)
Solutions
- Wrap the link in an array: links: ['https://example.com']
- Normalize before calling: links: Array.isArray(link) ? link : [link]
- Omit the links field entirely if you have no links (undefined/null keys are dropped by _clean)
Example fix
// before
const svg = makeBadge({ message: 'docs', links: 'https://example.com' })
// after
const svg = makeBadge({ message: 'docs', links: ['https://example.com'] }) Defensive patterns
Strategy: type-guard
Validate before calling
if ('links' in badge && !Array.isArray(badge.links)) {
badge.links = [badge.links]
}
const svg = makeBadge(badge) Type guard
function isStringArray(v) {
return Array.isArray(v) && v.every(x => typeof x === 'string')
} Try / catch
try {
return makeBadge(badge)
} catch (e) {
if (e instanceof ValidationError && e.message.includes('`links`')) {
return makeBadge({ ...badge, links: [].concat(badge.links).filter(l => typeof l === 'string') })
}
throw e
} Prevention
- Always pass links as an array, even for a single URL
- Normalize scalar-or-array inputs at config load: [].concat(maybeLink)
- Add a schema check (e.g. zod) on the badge descriptor
When it happens
Trigger: makeBadge({ message: 'docs', links: 'https://example.com' }) — a single URL string instead of an array; also links: {} or links: 5. Any truthy links value that fails Array.isArray.
Common situations: Passing one link as a bare string because a single link 'obviously' doesn't need an array; deserializing config from YAML/TOML where a single-element link becomes a scalar; a template variable that is sometimes a string and sometimes an array.
Related errors
- Field `${field}` must be of type string
- makeBadge takes an argument of type object
- Field `message` is required
- Field `links` must not have more than 2 elements
- Field `style` must be one of (${styleValues.toString()})
AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30).
Data as JSON: /api/errors/29d438c331b5e352.
Report an issue: GitHub.