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

  1. Look up the allowed roles for your element kind in SEMANTIC_REGISTRY_V1[kind].roles and use one of those exact tokens.
  2. If you do not know the type, restrict yourself to roles that appear in any definition (the union exported via the registry).
  3. Drop the [role=...] clause and target the element by kind or id instead.
  4. 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

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


AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12). Data as JSON: /api/errors/a1e3f4a2169e21ed. Report an issue: GitHub.