{"record":{"id":"f3c348d75cb3ecf7","repo":"framework7io/framework7","slug":"attempting-to-extend-color-originalcolor-name-a","errorCode":null,"errorMessage":"Attempting to extend color ${originalColor.name} as a ${originalColor.isBackground ? \"background\" : \"foreground\"} with color ${extendedColor.name} as a ${extendedColor.isBackground ? \"background\" : \"foreground\"} for spec version ${specVersion}.","messagePattern":"Attempting to extend color (.+?) as a (.+?) with color (.+?) as a (.+?) for spec version (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/core/shared/material-color-utils.js","lineNumber":397,"sourceCode":"  static darkerUnsafe(tone, ratio) {\n    const darkerSafe = Contrast.darker(tone, ratio);\n    return darkerSafe < 0 ? 0 : darkerSafe;\n  }\n}\n\nclass DislikeAnalyzer {\n  static isDisliked(hct) {\n    const huePasses = Math.round(hct.hue) >= 90 && Math.round(hct.hue) <= 111, chromaPasses = Math.round(hct.chroma) > 16, tonePasses = Math.round(hct.tone) < 65;\n    return huePasses && chromaPasses && tonePasses;\n  }\n  static fixIfDisliked(hct) {\n    return DislikeAnalyzer.isDisliked(hct) ? Hct.from(hct.hue, hct.chroma, 70) : hct;\n  }\n}\n\nfunction validateExtendedColor(originalColor, specVersion, extendedColor) {\n  if (originalColor.name !== extendedColor.name) throw new Error(`Attempting to extend color ${originalColor.name} with color ${extendedColor.name} of different name for spec version ${specVersion}.`);\n  if (originalColor.isBackground !== extendedColor.isBackground) throw new Error(`Attempting to extend color ${originalColor.name} as a ${originalColor.isBackground ? \"background\" : \"foreground\"} with color ${extendedColor.name} as a ${extendedColor.isBackground ? \"background\" : \"foreground\"} for spec version ${specVersion}.`);\n}\n\nfunction extendSpecVersion(originlColor, specVersion, extendedColor) {\n  return validateExtendedColor(originlColor, specVersion, extendedColor), DynamicColor.fromPalette({\n    name: originlColor.name,\n    palette: s => s.specVersion === specVersion ? extendedColor.palette(s) : originlColor.palette(s),\n    tone: s => s.specVersion === specVersion ? extendedColor.tone(s) : originlColor.tone(s),\n    isBackground: originlColor.isBackground,\n    chromaMultiplier: s => {\n      const chromaMultiplier = s.specVersion === specVersion ? extendedColor.chromaMultiplier : originlColor.chromaMultiplier;\n      return void 0 !== chromaMultiplier ? chromaMultiplier(s) : 1;\n    },\n    background: s => {\n      const background = s.specVersion === specVersion ? extendedColor.background : originlColor.background;\n      return void 0 !== background ? background(s) : void 0;\n    },\n    secondBackground: s => {\n      const secondBackground = s.specVersion === specVersion ? extendedColor.secondBackground : originlColor.secondBackground;","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/framework7io/framework7/blob/655759126686766530a027b2f8f369c991d63d1c/src/core/shared/material-color-utils.js#L379-L415","documentation":"validateExtendedColor also asserts that the extended color's isBackground flag matches the original color's. Extending a foreground color with a background variant (or vice versa) for a spec version would produce roles with wrong background/foreground semantics, so the library throws.","triggerScenarios":"extendSpecVersion called where originalColor.isBackground !== extendedColor.isBackground for the given specVersion.","commonSituations":"Copying a DynamicColor definition as the spec-version extension but leaving the default isBackground value (false) when the original is a background; swapping color entries in the spec table; hand-writing a 2021/2025 spec variant of a background role.","solutions":["Set extendedColor.isBackground to match originalColor.isBackground.","Copy the original color definition (or use clone/fromPalette with the correct isBackground) when authoring a spec-version extension.","Restore the spec-version color tables from upstream material-color-utils."],"exampleFix":"// before\nDynamicColor.fromPalette({ name: 'surface', palette: p, isBackground: false });\n// after\nDynamicColor.fromPalette({ name: 'surface', palette: p, isBackground: true });","handlingStrategy":"validation","validationCode":"function validateBackgroundFlags(originalColor, extendedColor, specVersion) {\n  if (originalColor.isBackground !== extendedColor.isBackground) {\n    throw new Error(`spec ${specVersion}: isBackground mismatch for ${originalColor.name}`);\n  }\n}","typeGuard":"function backgroundFlagsMatch(original, extended) {\n  return original.isBackground === extended.isBackground;\n}","tryCatchPattern":"try {\n  extendSpecVersion(color, specVersion, ext);\n} catch (err) {\n  if (/as a (background|foreground) with color .* for spec version/.test(err.message)) {\n    ext = { ...ext, isBackground: color.isBackground };\n  } else throw err;\n}","preventionTips":["Always pass isBackground explicitly (never rely on defaults) when authoring DynamicColors.","Use clone()/fromPalette from the original color so flags carry over.","Lint or test that each spec-version extension matches name and isBackground of its original."],"tags":["material-design","color","spec-version","invariant"],"backgroundTag":"color-spec-name-mismatch","analyzedSha":"655759126686766530a027b2f8f369c991d63d1c","analyzedAt":"2026-09-02T19:48:40.711Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}