{"record":{"id":"47bb855a990490ba","repo":"badges/shields","slug":"unexpected-field-key-allowed-values-are-e","errorCode":null,"errorMessage":"Unexpected field '${key}'. Allowed values are (${expectedKeys.toString()})","messagePattern":"Unexpected field '(.+?)'\\. Allowed values are \\((.+?)\\)","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"badge-maker/lib/index.js","lineNumber":80,"sourceCode":"  const expectedKeys = [\n    'label',\n    'message',\n    'labelColor',\n    'color',\n    'style',\n    'logoBase64',\n    'links',\n    'idSuffix',\n  ]\n\n  const cleaned = {}\n  Object.keys(format).forEach(key => {\n    if (format[key] != null && key === 'logoBase64') {\n      cleaned.logo = format[key]\n    } else if (format[key] != null && expectedKeys.includes(key)) {\n      cleaned[key] = format[key]\n    } else {\n      throw new ValidationError(\n        `Unexpected field '${key}'. Allowed values are (${expectedKeys.toString()})`,\n      )\n    }\n  })\n\n  // Legacy.\n  cleaned.label = cleaned.label || ''\n\n  return cleaned\n}\n\n/**\n * Create a badge\n *\n * @param {object} format Object specifying badge data\n * @param {string} format.label (Optional) Badge label (e.g: 'build')\n * @param {string} format.message (Required) Badge message (e.g: 'passing')\n * @param {string} format.labelColor (Optional) Label color","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/badge-maker/lib/index.js#L62-L98","documentation":"makeBadge only accepts a fixed set of keys: label, message, labelColor, color, style, logoBase64, links, idSuffix. In _clean (badge-maker/lib/index.js:74-84), any key that is not in this whitelist throws — including null-valued unknown keys — because a null/unknown key falls into the else branch. This catches typos and stale options early.","triggerScenarios":"makeBadge({ message: 'x', colours: 'green' }) (typo), makeBadge({ message: 'x', labelColor: null, color: null }) (explicit nulls hit the else branch since format[key] != null fails), or passing extra metadata keys (e.g. { message: 'x', id: 1 }).","commonSituations":"Misspelling an option name ('colour' vs 'color', 'logo' vs 'logoBase64'), spreading an unrelated config object into the descriptor, carrying over option names from other badge libraries, or explicitly setting a field to null expecting it to be ignored.","solutions":["Remove unknown keys or fix the typo so the key matches the whitelist exactly","For optional fields, omit the key rather than setting it to null — note null values for KNOWN keys also throw here","Filter the descriptor: Object.fromEntries(Object.entries(o).filter(([k, v]) => v != null))"],"exampleFix":"// before\nconst svg = makeBadge({ label: 'build', message: 'passing', colour: 'green' })\n// after\nconst svg = makeBadge({ label: 'build', message: 'passing', color: 'green' })","handlingStrategy":"type-guard","validationCode":"const ALLOWED = ['label', 'message', 'labelColor', 'color', 'style', 'logoBase64', 'links', 'idSuffix']\nfor (const key of Object.keys(badge)) {\n  if (!ALLOWED.includes(key) || badge[key] == null) {\n    throw new Error(`bad descriptor key/value: ${key}`)\n  }\n}\nconst svg = makeBadge(badge)","typeGuard":"function isCleanDescriptor(v) {\n  const allowed = ['label','message','labelColor','color','style','logoBase64','links','idSuffix']\n  return typeof v === 'object' && v !== null &&\n    Object.keys(v).every(k => allowed.includes(k) && v[k] != null)\n}","tryCatchPattern":"try {\n  return makeBadge(badge)\n} catch (e) {\n  if (e instanceof ValidationError && e.message.startsWith('Unexpected field')) {\n    const key = e.message.match(/'(.+)'/)[1]\n    const { [key]: _, ...rest } = badge\n    return makeBadge(rest)\n  }\n  throw e\n}","preventionTips":["Check option spelling against the whitelist (color not colour, logoBase64 not logo)","Do not spread arbitrary config objects into the descriptor","Omit optional keys instead of setting them to null — null known keys also throw in _clean","Type the descriptor in TypeScript as the library's BadgeOptions interface"],"tags":["validation","unknown-field","schema-validation","typo"],"backgroundTag":"unexpected-property","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}