code4craft/webmagic · error · UnsupportedOperationException

$ can not apply to plain text. Please check whether you use…

Error message

$ can not apply to plain text. Please check whether you use a previous xpath with attribute select (/@href etc).

What it means

PlainText's $(selector) method (CSS-style selector) always throws UnsupportedOperationException because CSS selectors need a parsed DOM, and PlainText holds only text. The hint about a previous /@href attribute select indicates the chain already reduced the content to plain text.

Solutions

  1. Reorder so $() is applied to page.getHtml() before any text/attribute extraction
  2. Replace $() with regex() when operating on plain text
  3. Check the previous selector is not accidentally producing PlainText (e.g. /@href)

Example fix

// before
page.getHtml().links().$("a.title").all();
// after
page.getHtml().$("a.title").all();
Defensive patterns

Strategy: validation

Validate before calling

if (selectable instanceof PlainText) { throw new IllegalStateException("cannot call $ on plain text"); }

Type guard

boolean supportsCss(Selectable s) { return !(s instanceof PlainText); }

Try / catch

try { out = selectable.$("a.title"); } catch (UnsupportedOperationException e) { out = fallbackRegex(selectable); }

Prevention

When it happens

Trigger: Calling .$("...") on a PlainText Selectable, e.g. chaining $ after links(), regex(), or an attribute xpath that returned PlainText.

Common situations: WebMagic users chaining CSS selectors after .links() or .regex(); result of a previous extraction was plain strings, so subsequent $() has nothing to query.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of code4craft/webmagic@67816a19d6 (2026-09-08). Data as JSON: /api/errors/eabd3b8e3eec27bf. Report an issue: GitHub.

Appendix: source

Thrown at webmagic-core/src/main/java/us/codecraft/webmagic/selector/PlainText.java:37

    }

    public PlainText(String text) {
        this.sourceTexts = new ArrayList<String>();
        sourceTexts.add(text);
    }

    public static PlainText create(String text) {
        return new PlainText(text);
    }

    @Override
    public Selectable xpath(String xpath) {
        throw new UnsupportedOperationException("XPath can not apply to plain text. Please check whether you use a previous xpath with attribute select (/@href etc).");
    }

    @Override
    public Selectable $(String selector) {
		throw new UnsupportedOperationException("$ can not apply to plain text. Please check whether you use a previous xpath with attribute select (/@href etc).");
    }

    @Override
    public Selectable $(String selector, String attrName) {
		throw new UnsupportedOperationException("$ can not apply to plain text. Please check whether you use a previous xpath with attribute select (/@href etc).");
    }

    @Override
    public Selectable links() {
		throw new UnsupportedOperationException("Links can not apply to plain text. Please check whether you use a previous xpath with attribute select (/@href etc).");
    }

    @Override
    public List<Selectable> nodes() {
        List<Selectable> nodes = new ArrayList<Selectable>(getSourceTexts().size());
        for (String string : getSourceTexts()) {
            nodes.add(PlainText.create(string));
        }

View on GitHub (pinned to 67816a19d6)