amruthpillai/reactive-resume · error · Error

Unsupported or misplaced combinator.

Error message

Unsupported or misplaced combinator.

What it means

Thrown by compileComplex when a combinator child is not one of the four supported combinators (' ', '>', '+', '~'), or when a combinator appears with no preceding simple selector in the current compound (a leading/misplaced combinator). Both conditions make the selector structurally invalid for this compiler.

Source

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

			throw new Error("Custom class selectors are not supported.");
		case "PseudoElementSelector":
			throw new Error("Pseudo-elements are not supported.");
		default:
			throw new Error(`Unsupported selector node ${node.type}.`);
	}
}

function compileComplex(node: SelectorAst, context: CompileContext): CompiledComplexSelector {
	if (node.type !== "Selector") throw new Error("Expected a Selector AST.");

	const compounds: CompiledCompoundSelector[] = [];
	const combinators: Combinator[] = [];
	let selectors: CompiledSimpleSelector[] = [];
	for (const child of childrenOf(node)) {
		if (child.type === "Combinator") {
			const name = astName(child) as Combinator;
			if (![" ", ">", "+", "~"].includes(name) || selectors.length === 0) {
				throw new Error("Unsupported or misplaced combinator.");
			}
			validateCompound(selectors);
			compounds.push({ selectors });
			selectors = [];
			combinators.push(name);
			if (combinators.length > SEMANTIC_CSS_LIMITS_V1.maxCombinatorsPerSelector) {
				throw new Error("Selector has too many combinators.");
			}
			continue;
		}

		const selector = compileSimple(child, context);
		if (selector) selectors.push(selector);
	}

	if (selectors.length === 0 && compounds.length > 0) throw new Error("Selector cannot end with a combinator.");
	validateCompound(selectors);
	compounds.push({ selectors });

View on GitHub (pinned to 3a5b12e2a4)

Solutions

  1. Ensure each combinator has a simple selector on both sides: section > item.
  2. Use only the four supported combinators: descendant (space), child (>), next-sibling (+), subsequent-sibling (~).
  3. Trim leading/trailing combinators when generating selectors programmatically.

Example fix

// before
> section
// after
region > section
Defensive patterns

Strategy: validation

Validate before calling

const COMBINATORS = new Set([' ', '>', '+', '~']);
const noLeadingCombinator = /^[\s>+~]/.test(selector.trim()) === false;
const noDoubleCombinator = !/[\s>+~]{2,}/.test(selector.replace(' ', ' '));
// verify both before compiling programmatically built selectors

Type guard

const isRejected = (r) => r.selector === null && typeof r.error === 'string';

Try / catch

const result = compileSelector(selector);
if (result.selector === null && result.error === 'Unsupported or misplaced combinator.') {
  trimOrRewriteCombinators(selector);
}

Prevention

When it happens

Trigger: Writing a selector that starts with a combinator (> section), uses an unsupported combinator token, or has two combinators in a row (section > > item).

Common situations: String concatenation that drops the left-hand side; templating that emits a leading '>' or '+'; copy-paste leaving a dangling combinator; css-tree edge cases.

Related errors


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