amruthpillai/reactive-resume · error · Error

Selector name is missing.

Error message

Selector name is missing.

What it means

astName reads the name of a csstree SelectorAst node. It returns identifier(node.name) when name is a string, or identifier(node.name.name) for the {name:{name}} shape; if neither holds it throws 'Selector name is missing.' This indicates an AST node the selector compiler expected to have a name (type/pseudo-class/attribute identifier) arrived without one.

Source

Thrown at packages/resume/src/stylesheet/selector.ts:93

const knownAttributes = new Set([
	"id",
	"role",
	...Object.values(SEMANTIC_REGISTRY_V1).flatMap((definition) => definition.attributes),
]);
const knownRoles = new Set(Object.values(SEMANTIC_REGISTRY_V1).flatMap((definition) => definition.roles));

function childrenOf(node: SelectorAst): SelectorAst[] {
	return node.children ? [...node.children] : [];
}

function identifier(value: string): string {
	return csstree.ident.decode(value);
}

function astName(node: SelectorAst): string {
	if (typeof node.name === "string") return identifier(node.name);
	if (node.name && typeof node.name.name === "string") return identifier(node.name.name);
	throw new Error("Selector name is missing.");
}

function attributeValue(node: SelectorAst): string | null {
	if (!node.value) return null;
	if (typeof node.value.value === "string") return node.value.value;
	if (typeof node.value.name === "string") return identifier(node.value.name);
	throw new Error("Attribute value is missing.");
}

function allowedRoles(type: SemanticNode["kind"] | null): ReadonlySet<string> {
	return type ? new Set(SEMANTIC_REGISTRY_V1[type].roles) : knownRoles;
}

function roleValueIsKnown(matcher: AttributeMatcher | null, value: string | null, roles: ReadonlySet<string>): boolean {
	if (!matcher || value === null) return roles.size > 0;
	if (matcher === "~=") return roles.has(value);
	if (matcher === "=") {
		const tokens = value.split(/\s+/).filter(Boolean);

View on GitHub (pinned to 3a5b12e2a4)

Solutions

  1. Simplify the offending selector to standard form (every type/pseudo/attribute needs a name token).
  2. Run the selector through csstreefork/use-parse in a scratch test to find which node lacks a name.
  3. Pin or align the csstree version with what the mapper was written against.
  4. Report the failing selector to the user with a clear 'invalid selector' message rather than crashing.

Example fix

/* before: bare pseudo, nameless node */
selector { :: {} }
/* after */
selector { ::after {} }
Defensive patterns

Strategy: try-catch

Validate before calling

import { parse } from 'css-tree';
try { parse(selector, { context: 'selector' }); } catch { throw new Error('Invalid selector syntax'); }

Type guard

function hasName(node: any): boolean {
  return typeof node?.name === 'string' || typeof node?.name?.name === 'string';
}

Try / catch

try { compileSelector(selector); }
catch (e) { if (/Selector name is missing/.test(String((e as Error).message))) { reportInvalidSelector(selector); return; } throw e; }

Prevention

When it happens

Trigger: A user-authored or AI-generated selector that csstree parsed into an unexpected node shape; a selector containing a bare punctuation construct that yields a nameless node; a csstree version change altering AST node shapes.

Common situations: Editing the semantic stylesheet with a malformed selector (e.g. ':' alone, '::' bare, or a pseudo with no name); upgrading csstree without updating the mapper; a selector with non-ASCII/control characters that parse oddly.

Related errors


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