amruthpillai/reactive-resume · error · Error
Selector uses an unknown role.
Error message
Selector uses an unknown role.
What it means
Thrown by validateCompound when an attribute selector targeting [role] references a role value that is not registered for the compound's semantic element type (or for any type when the compound has no type selector). The SEMANTIC_REGISTRY_V1 map enumerates the only legal role tokens per kind; :nth-child-style whitespace token lists and ~= single tokens must all be members of that set.
Source
Thrown at packages/resume/src/stylesheet/selector.ts:131
}
return [...roles].some((role) => matchesAttribute(role, matcher, value));
}
function validateCompound(selectors: readonly CompiledSimpleSelector[]): void {
const types = selectors.filter(
(selector): selector is Extract<CompiledSimpleSelector, { type: "type" }> => selector.type === "type",
);
if (types.length > 1) throw new Error("A compound selector can contain only one type selector.");
const type = types[0]?.name ?? null;
for (const selector of selectors) {
if (selector.type !== "attribute") continue;
if (selector.name === "id") continue;
if (selector.name === "role") {
if (!roleValueIsKnown(selector.matcher, selector.value, allowedRoles(type))) {
throw new Error("Selector uses an unknown role.");
}
continue;
}
if (type && !(SEMANTIC_REGISTRY_V1[type].attributes as readonly string[]).includes(selector.name)) {
throw new Error(`Attribute ${selector.name} is not available on ${type}.`);
}
}
}
function compileNth(
node: SelectorAst,
name: "nth-child" | "nth-of-type",
context: CompileContext,
): CompiledSimpleSelector {
const nth = childrenOf(node);
if (nth.length !== 1 || nth[0]?.type !== "Nth" || !nth[0].nth) {
throw new Error(`:${name} requires one An+B expression.`);View on GitHub (pinned to 3a5b12e2a4)
Solutions
- Look up the allowed roles for your element kind in SEMANTIC_REGISTRY_V1[kind].roles and use one of those exact tokens.
- If you do not know the type, restrict yourself to roles that appear in any definition (the union exported via the registry).
- Drop the [role=...] clause and target the element by kind or id instead.
- For ~= matcher, pass a single token; for = matcher, ensure every whitespace-separated token is a registered role.
Example fix
// before item[role~="team-lead"] // after item[role~="experience-role"]
Defensive patterns
Strategy: validation
Validate before calling
import { SEMANTIC_REGISTRY_V1 } from '@reactive-resume/resume';
const roleIsKnown = (type, matcher, value) => {
const roles = type
? new Set(SEMANTIC_REGISTRY_V1[type].roles)
: new Set(Object.values(SEMANTIC_REGISTRY_V1).flatMap(d => d.roles));
if (!matcher || value === null) return roles.size > 0;
if (matcher === '~=') return roles.has(value);
if (matcher === '=') return value.split(/\s+/).filter(Boolean).every(t => roles.has(t));
return [...roles].some(r =>
matcher === '|=' ? r === value || r.startsWith(value + '-')
: matcher === '^=' ? r.startsWith(value)
: matcher === '$=' ? r.endsWith(value)
: matcher === '*=' ? r.includes(value)
: false);
};
// call before building [role=...] selectors Type guard
import type { CompileSelectorResult } from '@reactive-resume/resume';
const isRejected = (r: CompileSelectorResult): r is CompileSelectorResult & { selector: null; error: string } =>
r.selector === null && typeof r.error === 'string'; Try / catch
const result = compileSelector(selector);
if (result.selector === null) {
// result.error === 'Selector uses an unknown role.'
reportToSelectorAuthor(result.error, selector);
} Prevention
- Source role tokens from SEMANTIC_REGISTRY_V1[kind].roles rather than guessing.
- Treat the registry as the single source of truth and lint selectors against it at authoring time.
- Remember ARIA role names from HTML do not carry over to this semantic model.
When it happens
Trigger: Authoring [role~="fake-role"], item[role="experience-role nonexistent"], or any [role|=...]/[^=...]/[$=...]/[*=...] whose pattern matches zero roles registered for the targeted kind (e.g. region[role~="primary-text"] where region declares no roles).
Common situations: Copying ARIA role names from HTML/DOM mental models into resume semantic CSS; guessing role names without consulting the registry; pairing a role that exists on 'field' with a different element like 'section'.
Related errors
- Attribute ${selector.name} is not available on ${type}.
- Unknown semantic element ${name}.
- Unknown semantic attribute ${name}.
- :${name} does not accept arguments.
- Unsupported pseudo-class :${name}.
AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12).
Data as JSON: /api/errors/a1e3f4a2169e21ed.
Report an issue: GitHub.