code4craft/webmagic · error · IllegalStateException

Only one of 'ExtractBy ComboExtract ExtractByUrl' can be…

Error message

Only one of 'ExtractBy ComboExtract ExtractByUrl' can be added to a field!

What it means

PageModelExtractor.init validates annotated model fields: a field may carry at most one of @ExtractBy, @ComboExtract, or @ExtractByUrl. When getAnnotationExtractBy and getAnnotationExtractCombo both return extractors for the same field, IllegalStateException is thrown at model setup time.

Solutions

  1. Remove one of the conflicting annotations from the field
  2. Move one extraction to a separate field if both values are needed
  3. Use @ComboExtract alone to combine multiple sub-extractors instead of stacking @ExtractBy

Example fix

// before
@ExtractBy("//title/text()")
@ComboExtract(@ExtractBy(value = "//h1/text()"))
private String title;
// after
@ExtractBy("//title/text()")
private String title;
Defensive patterns

Strategy: validation

Validate before calling

for (Field f : modelClass.getDeclaredFields()) { int n = countAnnotations(f, ExtractBy.class, ComboExtract.class, ExtractByUrl.class); if (n > 1) throw new IllegalStateException(f + " has multiple extract annotations"); }

Try / catch

try { spider = OOSpider.create(Model.class, pipeline, urls); } catch (IllegalStateException e) { log.error("model annotation conflict: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Declaring a model field annotated with both @ExtractBy and @ComboExtract, then calling OOSpider.create(...) or PageModelExtractor.create(clazz).

Common situations: Copy-pasting annotations between fields and leaving two behind; merging extractor classes where one field gained @ComboExtract without removing @ExtractBy.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at webmagic-extension/src/main/java/us/codecraft/webmagic/model/PageModelExtractor.java:72

    private Logger logger = LoggerFactory.getLogger(getClass());

    public static PageModelExtractor create(Class clazz) {
        PageModelExtractor pageModelExtractor = new PageModelExtractor();
        pageModelExtractor.init(clazz);
        return pageModelExtractor;
    }

    private void init(Class clazz) {
        this.clazz = clazz;
        initClassExtractors();
        fieldExtractors = new ArrayList<FieldExtractor>();
        for (Field field : ClassUtils.getFieldsIncludeSuperClass(clazz)) {
            field.setAccessible(true);
            FieldExtractor fieldExtractor = getAnnotationExtractBy(clazz, field);
            FieldExtractor fieldExtractorTmp = getAnnotationExtractCombo(clazz, field);
            if (fieldExtractor != null && fieldExtractorTmp != null) {
                throw new IllegalStateException("Only one of 'ExtractBy ComboExtract ExtractByUrl' can be added to a field!");
            } else if (fieldExtractor == null && fieldExtractorTmp != null) {
                fieldExtractor = fieldExtractorTmp;
            }
            fieldExtractorTmp = getAnnotationExtractByUrl(clazz, field);
            if (fieldExtractor != null && fieldExtractorTmp != null) {
                throw new IllegalStateException("Only one of 'ExtractBy ComboExtract ExtractByUrl' can be added to a field!");
            } else if (fieldExtractor == null && fieldExtractorTmp != null) {
                fieldExtractor = fieldExtractorTmp;
            }
            if (fieldExtractor != null) {
                fieldExtractor.setObjectFormatter(new ObjectFormatterBuilder().setField(field).build());
                fieldExtractors.add(fieldExtractor);
            }
        }
    }

    private FieldExtractor getAnnotationExtractByUrl(Class clazz, Field field) {
        FieldExtractor fieldExtractor = null;

View on GitHub (pinned to 67816a19d6)