[tomcat8] Tomcat: java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens

I am getting below stack trace when I am deploying my application in a multi-server Apache Tomcat 8 environment. I am getting this error frequently, and it seems it is blocking the tomcat thread:

INFO [http-nio-80-exec-4461] org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header
 Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
 java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens
 at org.apache.coyote.http11.AbstractNioInputBuffer.parseRequestLine(AbstractNioInputBuffer.java:233)
 at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1017)
 at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1524)
 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1480)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.lang.Thread.run(Unknown Source)

Can any one direct me how to troubleshoot or narrow down such an exeption? I am not getting any reference to any of my application source files. I tried to google around, and in of the links it said, you are trying to access http url through https, which seems unlikely. I am not getting this error, when the application runs on a single Tomcat 8 instance. I get this only in a multi-server environment.

I am also sharing the meta tags I have embedded on each page, if that helps to identify the cause.

<%
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("Cache-Control", "no-store");
    response.setDateHeader("Expires", 0);
    response.setHeader("Pragma", "no-cache");
%>


<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1">

I am also using the following in a few pages, which basically is same as above:

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Cache-Control" content="private" />
<meta http-equiv="Cache-Control" content="no-store" />
<meta http-equiv="Pragma" content="no-cache" />

Even if anyone helps in giving a direction to my troubleshooting attempt, that will be useful, as currently I have no idea where to look into.

This question is related to tomcat8 illegalargumentexception

The answer is


You are calling local server with http://localhost:8080/foo/bar. Call it with https://localhost:8080/foo/bar. This solves the problem


I received this exception unrelated to any TLS issues. In my case the Content-Length header value did not match the body length.


I got this error resolved by doing 2 things in chrome browser:

  1. Pressed Ctrl + Shift + Delete and cleared all browsing data from beginning.
  2. Go to Chrome's : Settings ->Advanced Settings -> Open proxy settings -> Internet Properties then Go to the Content window and click on the Clear SSL State Button.

This site has this information and other options as well : https://www.thesslstore.com/blog/fix-err-ssl-protocol-error/


You can also try turning off the SSL option in settings, in case you are sending it through POSTMAN


In my case I had to clear browser history/cookies to get rid of this error.


This usually happens when you are using a URI scheme that is not supported by the server in which the app is deployed. So, you might either want to check what all schemes your server supports and modify your request URI accordingly, or, you might want to add the support for that scheme in your server. The scope of your application should help you decide on this.


It happened to me when I had a same port used in ssh tunnel SOCKS to run Proxy in 8080 port and my server and my firefox browser proxy was set to that port and got this issue.


I got the same exception when I locally tested. The problem was a URL schema in my request.

Change https:// to http:// in your client url.

Probably it helps.


Answering this old question (for others which may help)

Configuring your httpd conf correctly will make the problem solved. Install any httpd server, if you don't have one.

Listing my config here.

[smilyface@box002 ~]$ cat /etc/httpd/conf/httpd.conf | grep shirts | grep -v "#"


        ProxyPass /shirts-service http://local.box002.com:16743/shirts-service
        ProxyPassReverse /shirts-service http://local.box002.com:16743/shirts-service
        ProxyPass /shirts http://local.box002.com:16443/shirts
        ProxyPassReverse /shirts http://local.box002.com:16443/shirts
        ...
        ...
        ...

edit the file as above and then restart httpd as below

[smilyface@box002 ~]$ sudo service httpd restart


And then request with with https will work without exception.
Also request with http will forward to https ! No worries.


I was getting the same exception, whenever a page was getting loaded,

NFO: Error parsing HTTP request header
 Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens
    at org.apache.coyote.http11.InternalInputBuffer.parseRequestLine(InternalInputBuffer.java:139)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1028)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

I found that one of my page URL was https instead of http, when I changed the same, error was gone.


I had this issue when working on a Java Project in Debian 10 with Tomcat as the application server.

The issue was that the application already had https defined as it's default protocol while I was using http to call the application in the browser. So when I try running the application I get this error in my log file:

INFO [http-nio-80-exec-4461] org.apache.coyote.http11.AbstractHttp11Processor.process Error parsing HTTP request header

Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.

java.lang.IllegalArgumentException: Invalid character found in method name. HTTP method names must be tokens

I however tried using the https protocol in the browser but it didn't connect throwing the error:

Here's how I solved it:

You need a certificate to setup the https protocol for the application. You can obtain certificates from Let's Encrypt. For me the easiest route was creating a obtaining a self-signed certificate. .

I first had to create a keystore file for the application, more like a self-signed certificate for the https protocol:

sudo keytool -genkey -keyalg RSA -alias tomcat -keystore /usr/share/tomcat.keystore

Note: You need to have Java installed on the server to be able to do this. Java can be installed using sudo apt install default-jdk.

Next, I added a https Tomcat server connector for the application in the Tomcat server configuration file (/opt/tomcat/conf/server.xml):

sudo nano /opt/tomcat/conf/server.xml

Add the following to the configuration of the application. Notice that the keystore file location and password are specified. Also a port for the https protocol is defined, which is different from the port for the http protocol:

<Connector protocol="org.apache.coyote.http11.Http11Protocol"
           port="8443" maxThreads="200" scheme="https"
           secure="true" SSLEnabled="true"
           keystoreFile="/usr/share/tomcat.keystore"
           keystorePass="my-password"
           clientAuth="false" sslProtocol="TLS"
           URIEncoding="UTF-8"
           compression="force"
           compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css"/>

So the full server configuration for the application looked liked this in the Tomcat server configuration file (/opt/tomcat/conf/server.xml):

<Service name="my-application">
  <Connector protocol="org.apache.coyote.http11.Http11Protocol"
             port="8443" maxThreads="200" scheme="https"
             secure="true" SSLEnabled="true"
             keystoreFile="/usr/share/tomcat.keystore"
             keystorePass="my-password"
             clientAuth="false" sslProtocol="TLS"
             URIEncoding="UTF-8"
             compression="force"
             compressableMimeType="text/html,text/xml,text/plain,text/javascript,text/css"/>

  <Connector port="8009" protocol="HTTP/1.1"
             connectionTimeout="20000"
             redirectPort="8443" />

  <Engine name="my-application" defaultHost="localhost">
     <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
             resourceName="UserDatabase"/>
    </Realm>

    <Host name="localhost"  appBase="webapps"
          unpackWARs="true" autoDeploy="true">

        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
             prefix="localhost_access_log" suffix=".txt"
             pattern="%h %l %u %t &quot;%r&quot; %s %b" />

    </Host>
  </Engine>
</Service>

This time when I tried accessing the application from the browser using:

https://my-server-ip-address:https-port

In my case it was:

https:35.123.45.6:8443

it worked fine. Although, I had to accept a warning which added a security exception for the website since the certificate used is a self-signed one.

That's all.

I hope this helps


This exception can occur when you try to execute HTTPS request from client on endpoint which isn't HTTPS enabled. Client will encrypt request data when server is expecting raw data.


I know this is an old thread, but there is a particular case when this may happen:

If you are using AWS api gateway coupled with a VPC link, and if the Network Load Balancer has proxy protocol v2 enabled, a 400 Bad Request will happen as well.

Took me the whole afternoon to figure it out, so if it may help someone I'd be glad :)


In case someone is using swagger:

Change the Scheme to HTTP or HTTPS, depend on needs, prior to hit the execute.

Postman:

Change the URL Path to http:// or https:// in the url address