stanfordnlp/CoreNLP · error · IOException

Specifying an inputSerializer other than…

Error message

Specifying an inputSerializer other than ProtobufAnnotationSerializer is now deprecated for security reasons.  See https://github.com/stanfordnlp/CoreNLP/security/advisories/GHSA-wv35-hv9v-526p  If you have need for a different class, please post about your use case on the CoreNLP github.

What it means

Since the GHSA-wv35-hv9v-526p security advisory, StanfordCoreNLPServer only accepts the default ProtobufAnnotationSerializer as inputSerializer. Supplying any other class when POSTing 'serialized' input is rejected with an IOException to block unsafe deserialization of arbitrary classes.

Solutions

  1. Remove the inputSerializer property so the default ProtobufAnnotationSerializer is used
  2. Send text or json inputFormat instead of serialized if you need a custom pipeline format
  3. Post your use case on the CoreNLP GitHub issues as the message suggests if you truly need a custom serializer

Example fix

// before
props.setProperty("inputSerializer", "com.example.MySerializer");
// after
props.remove("inputSerializer"); // or send inputFormat=text/json
Defensive patterns

Strategy: validation

Validate before calling

String ser = props.getProperty("inputSerializer");
if (ser != null && !"edu.stanford.nlp.pipeline.ProtobufAnnotationSerializer".equals(ser)) {
  props.remove("inputSerializer"); // reject custom serializers post-GHSA-wv35-hv9v-526p
}

Try / catch

try {
  sendSerializedRequest(props);
} catch (IOException e) {
  if (e.getMessage().contains("deprecated for security reasons")) {
    props.remove("inputSerializer");
    sendSerializedRequest(props);
  } else throw e;
}

Prevention

When it happens

Trigger: POSTing serialized input to the server with -inputSerializer (or inputSerializer property) set to any class other than edu.stanford.nlp.pipeline.ProtobufAnnotationSerializer, on inputFormat=serialized.

Common situations: Upgrading CoreNLP after the security fix while old client configs still set a custom inputSerializer; following outdated tutorials that showed custom serializers; internal tooling that previously deserialized custom Annotation pipelines.

Understand the failure class

Background: "is deprecated and will be removed" — deprecation warnings for old API names, keywords, and options, and how to migrate before the removal release — this error's family across 29 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/0048f0330b4fe33e. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/pipeline/StanfordCoreNLPServer.java:337

          try {
            text = URLDecoder.decode(text, encoding);
          } catch (IllegalArgumentException e) {
            // ignore decoding errors so that libraries which don't specify a content type might not fail
          }
        }
        // We use to trim. But now we don't. It seems like doing that is illegitimate. text = text.trim();

        // Read the annotation
        Annotation annotation = new Annotation(text);
        // Set the date (if provided)
        if (date != null) {
          annotation.set(CoreAnnotations.DocDateAnnotation.class, date);
        }
        return annotation;
      case "serialized":
        String inputSerializerName = props.getProperty("inputSerializer", ProtobufAnnotationSerializer.class.getName());
        if (!inputSerializerName.equals(ProtobufAnnotationSerializer.class.getName())) {
          throw new IOException("Specifying an inputSerializer other than ProtobufAnnotationSerializer is now deprecated for security reasons.  See https://github.com/stanfordnlp/CoreNLP/security/advisories/GHSA-wv35-hv9v-526p  If you have need for a different class, please post about your use case on the CoreNLP github.");
        }
        AnnotationSerializer serializer = new ProtobufAnnotationSerializer();
        Pair<Annotation, InputStream> pair = serializer.read(httpExchange.getRequestBody());
        return pair.first;
      default:
        throw new IOException("Could not parse input format: " + inputFormat);
    }
  }

  private String getContentType(Headers headers) {
    String contentType = URL_ENCODED;
    if (headers.containsKey("Content-type")) {
      contentType = headers.getFirst("Content-type").split(";")[0].trim();
    }
    return contentType;
  }

  private String getEncoding(Headers headers) {

View on GitHub (pinned to 1b7edd19c4)