amruthpillai/reactive-resume · error · Error

Attribute value is missing.

Error message

Attribute value is missing.

What it means

attributeValue extracts the value of a csstree attribute selector node. It returns node.value.value when it's a string, or identifier(node.value.name) for the identifier shape; if node.value exists but neither field is a usable string, it throws 'Attribute value is missing.' Reached only when node.value is truthy (otherwise it returns null earlier).

Source

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

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);
		return tokens.length > 0 && tokens.every((token) => roles.has(token));
	}

	return [...roles].some((role) => matchesAttribute(role, matcher, value));
}

function validateCompound(selectors: readonly CompiledSimpleSelector[]): void {

View on GitHub (pinned to 3a5b12e2a4)

Solutions

  1. Quote or correct the attribute value: [role='section'] instead of [role=].
  2. If the value is meant to be empty, remove the attribute selector; attribute matching requires a value here.
  3. Add a test fixture of the failing selector and confirm the AST shape against the handled branches; extend attributeValue if a legitimate shape appears.
  4. Pin csstree to the version the mapper targets.

Example fix

/* before: missing value */
[role=] { ... }
/* after */
[role='section'] { ... }
Defensive patterns

Strategy: try-catch

Validate before calling

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

Type guard

function hasAttributeValue(node: any): boolean {
  return !node.value || typeof node.value.value === 'string' || typeof node.value.name === 'string';
}

Try / catch

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

Prevention

When it happens

Trigger: An attribute selector whose value is a non-string, non-identifier AST shape, e.g. [role=] with no value, or [x=123] encoded in a way csstree represents as a numeric/raw node; a malformed [attr=val] construct.

Common situations: User typed an attribute selector with a missing or unquoted complex value; csstree representation differs from the two handled shapes after a library bump; an AI-generated selector with broken attribute syntax.

Related errors


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