When running Apache Flink, you might encounter the following error message during startup or execution:

1
java.lang.NoSuchMethodError: org.apache.commons.cli.CommandLine.hasOption

For example, when I use Flink version 1.17.2 and start a job in Application Mode, the job is submitted successfully and runs as expected. The command and output information are as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ /data/flink/flink-1.17.2/bin/flink run-application -t yarn-application -p 3 -Djobmanager.memory.process.size=1024m -Dtaskmanager.memory.process.size=2048m -Dtaskmanager.memory.network.max=64mb -c com.my.flink.etl.dws.trd.OrderSummaryJob -Dyarn.application.name="com.my.flink.etl.dws.trd.OrderSummaryJob" -Dyarn.application.type="Flink 1.17.2" /data/flink/my-flink-etl-jar/dws-trd-ord-summary.jar

Setting HBASE_CONF_DIR=/etc/hbase/conf because no HBASE_CONF_DIR was set.
2024-11-05 14:05:05,849 WARN org.apache.flink.yarn.configuration.YarnLogConfigUtil [] - The configuration directory ('/data/flink/flink-1.17.2/conf') already contains a LOG4J config file.If you want to use logback, then please delete or rename the log configuration file.
2024-11-05 14:05:06,019 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - No path for the flink jar passed. Using the location of class org.apache.flink.yarn.YarnClusterDescriptor to locate the jar
2024-11-05 14:05:06,091 INFO org.apache.hadoop.yarn.client.ConfiguredRMFailoverProxyProvider [] - Failing over to rm2
2024-11-05 14:05:06,128 INFO org.apache.hadoop.conf.Configuration [] - found resource resource-types.xml at file:/etc/hadoop/3.1.4.0-315/0/resource-types.xml
2024-11-05 14:05:06,166 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Cluster specification: ClusterSpecification{masterMemoryMB=1024, taskManagerMemoryMB=2048, slotsPerTaskManager=1}2024-11-05 14:05:06,396 WARN org.apache.hadoop.hdfs.shortcircuit.DomainSocketFactory [] - The short-circuit local reads feature cannot be used because libhadoop cannot be loaded.
2024-11-05 14:05:07,683 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Removing 'localhost' Key: 'jobmanager.bind-host' , default: null (fallback keys: []) setting from effective configuration; using '0.0.0.0' instead.
2024-11-05 14:05:07,684 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Removing 'localhost' Key: 'taskmanager.bind-host' , default: null (fallback keys: []) setting from effective configuration; using '0.0.0.0' instead.
2024-11-05 14:05:07,708 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Cannot use kerberos delegation token manager, no valid kerberos credentials provided.
2024-11-05 14:05:07,712 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Submitting application master application_1723014599670_0040
2024-11-05 14:05:07,755 INFO org.apache.hadoop.yarn.client.api.impl.YarnClientImpl [] - Submitted application application_1723014599670_0040
2024-11-05 14:05:07,755 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Waiting for the cluster to be allocated
2024-11-05 14:05:07,756 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Deploying cluster, current state ACCEPTED
2024-11-05 14:05:12,524 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - YARN application has been deployed successfully.
2024-11-05 14:05:12,525 INFO org.apache.flink.yarn.YarnClusterDescriptor [] - Found Web Interface flink-onyarn-node-01:41684 of application 'application_1723014599670_0040'.

Now, I want to test the savepoint feature and observe the job’s behavior when stopping and restarting it. However, when executing the Flink command (to submit a job and specify a savepoint to resume from), I encounter the following error. The same issue also occurs when running flink stop.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 /data/flink/flink-1.17.2/bin/flink run-application -t yarn-application -p 3 -Djobmanager.memory.process.size=1024m -Dtaskmanager.memory.process.size=2048m -Dtaskmanager.memory.network.max=64mb -c com.my.flink.etl.dws.trd.OrderSummaryJob -Dyarn.application.name="com.my.flink.etl.dws.trd.OrderSummaryJob" -Dyarn.application.type="Flink 1.17.2" -s hdfs:/flink-checkpoints/flink-1.17.2/ea98ue43a2fc63d4631895af4604dd43e/chk-102 /data/flink/my-flink-etl-jar/dws-trd-ord-summary.jar

Setting HBASE_CONF_DIR=/etc/hbase/conf because no HBASE_CONF_DIR was set.
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/data/flink/flink-1.17.2/lib/log4j-slf4j-impl-2.17.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/hdp/3.1.4.0-315/hadoop/lib/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
java.lang.NoSuchMethodError: org.apache.commons.cli.CommandLine.hasOption(Lorg/apache/commons/cli/Option;)Z
at org.apache.flink.client.cli.CliFrontendParser.createSavepointRestoreSettings(CliFrontendParser.java:631)
at org.apache.flink.client.cli.ProgramOptions.<init>(ProgramOptions.java:119)
at org.apache.flink.client.cli.CliFrontend.runApplication(CliFrontend.java:198)
at org.apache.flink.client.cli.CliFrontend.parseAndRun(CliFrontend.java:1098)
at org.apache.flink.client.cli.CliFrontend.lambda$mainInternal$9(CliFrontend.java:1189)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1876)
at org.apache.flink.runtime.security.contexts.HadoopSecurityContext.runSecured(HadoopSecurityContext.java:41)
at org.apache.flink.client.cli.CliFrontend.mainInternal(CliFrontend.java:1189)
at org.apache.flink.client.cli.CliFrontend.main(CliFrontend.java:1157)

This error typically indicates an issue with version conflicts or the availability of the required method within the libraries that Flink is using. In this case, the error is related to the Apache Commons CLI library, which is used by Flink for command-line argument parsing.

In this article, we will walk through the possible causes and solutions for this error, so you can get your Flink application up and running.

Understanding the Error

The error java.lang.NoSuchMethodError suggests that at runtime, your application is trying to invoke a method that is not present in the version of the library being used. The method in question is hasOption, which belongs to the CommandLine class of the Apache Commons CLI library.

Flink internally relies on Apache Commons CLI for parsing command-line options, and it expects a specific version of the library. However, if there’s a version mismatch between the library that Flink was compiled against and the one available at runtime, the hasOption method might not exist, causing the error.

Common Causes of the Error

There are a few potential causes for this error:

  1. Version Conflict with Apache Commons CLI: If your project uses a different version of the Apache Commons CLI library than what Flink expects, the hasOption method might not exist or could be defined differently.
  2. Incompatible Dependencies: Other libraries in your project might bring in a different version of the Apache Commons CLI library, which could override the version expected by Flink.
  3. Incorrect Classpath Configuration: If your Flink setup includes additional or outdated versions of libraries that conflict with the ones included in the Flink distribution, it could result in runtime issues like this.
  4. Missing related jar packages.

Solutions to Resolve the Issue

Verify That the commons-cli Jar Package Exists

Given that the error is a java.lang.NoSuchMethodError, it’s likely due to a missing JAR file. Navigate to the lib directory under the Flink installation folder, as shown below, and you’ll find that the common-cli JAR is indeed missing. To fix this, simply download the JAR and place it in the lib directory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ ll lib/
total 202380
-rw-r--r-- 1 hadoop hadoop 196491 Nov 13 2023 flink-cep-1.17.2.jar
-rw-r--r-- 1 hadoop hadoop 542629 Nov 13 2023 flink-connector-files-1.17.2.jar
-rw-rw-r-- 1 hadoop hadoop 268555 Nov 4 18:42 flink-connector-jdbc-3.1.2-1.17.jar
-rw-r--r-- 1 hadoop hadoop 102470 Nov 13 2023 flink-csv-1.17.2.jar
-rw-r--r-- 1 hadoop hadoop 121809282 Nov 13 2023 flink-dist-1.17.2.jar
-rw-r--r-- 1 hadoop hadoop 180246 Nov 13 2023 flink-json-1.17.2.jar
-rw-r--r-- 1 hadoop hadoop 21043317 Nov 13 2023 flink-scala_2.12-1.17.2.jar
-rw-r--r-- 1 hadoop hadoop 59381853 Dec 7 2023 flink-shaded-hadoop-3-uber-3.1.1.7.1.1.0-565-9.0.jar
-rw-r--r-- 1 hadoop hadoop 15407408 Nov 13 2023 flink-table-api-java-uber-1.17.2.jar
-rw-r--r-- 1 hadoop hadoop 38194169 Nov 13 2023 flink-table-planner-loader-1.17.2.jar
-rw-r--r-- 1 hadoop hadoop 3146303 Nov 13 2023 flink-table-runtime-1.17.2.jar
-rw-rw-r-- 1 hadoop hadoop 1878533 Dec 10 2023 jna-5.14.0.jar
-rw-rw-r-- 1 hadoop hadoop 1369287 Dec 10 2023 jna-platform-5.14.0.jar
-rw-r--r-- 1 hadoop hadoop 208006 Jun 1 2022 log4j-1.2-api-2.17.1.jar
-rw-r--r-- 1 hadoop hadoop 301872 Jun 1 2022 log4j-api-2.17.1.jar
-rw-r--r-- 1 hadoop hadoop 1790452 Jun 1 2022 log4j-core-2.17.1.jar
-rw-r--r-- 1 hadoop hadoop 24279 Jun 1 2022 log4j-slf4j-impl-2.17.1.jar
-rw-rw-r-- 1 hadoop hadoop 975591 Nov 25 2023 oshi-core-6.4.8.jar

You can download the JAR file using the following command:

1
wget https://repo1.maven.org/maven2/commons-cli/commons-cli/1.5.0/commons-cli-1.5.0.jar

The first step is to verify that you are using a compatible version of Flink and Apache Commons CLI. Apache Flink uses a specific version of Apache Commons CLI, and running Flink with an incompatible version can lead to errors.

  1. Check Flink Version: Find out which version of Flink you are using and check the corresponding version of Apache Commons CLI in its dependencies.
    • You can check the Flink version by running flink --version.
    • Flink dependencies, including Apache Commons CLI, are often specified in the pom.xml (for Maven-based builds) or build.gradle (for Gradle-based builds).
  2. Ensure Correct Version of Apache Commons CLI: If Flink relies on a specific version of Commons CLI, make sure your project includes the same version.For example, if you’re using Maven, you can specify the dependency version explicitly:
1
2
3
4
5
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version> <!-- Replace with Flink's expected version -->
</dependency>

Exclude Conflicting Dependencies

If your project or any of the libraries you’re using brings in a conflicting version of Apache Commons CLI, you can exclude it from your dependencies.

For example, in Maven, you can exclude a conflicting dependency like this:

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-core</artifactId>
<version>YOUR_FLINK_VERSION</version>
<exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-cli</artifactId>
</exclusion>
</exclusions>
</dependency>

This will prevent the conflicting version of the library from being included, allowing Flink to use its bundled version of Commons CLI.

In Gradle, you can exclude a dependency in a similar manner:

1
2
3
4
5
dependencies {
implementation('org.apache.flink:flink-core:YOUR_FLINK_VERSION') {
exclude group: 'org.apache.commons', module: 'commons-cli'
}
}

Update Dependencies to Latest Versions

Sometimes the issue arises due to the use of outdated or unsupported versions of libraries. Ensure all dependencies in your project are up to date, particularly Apache Commons CLI and Flink.

To update dependencies in Maven, run:

1
mvn versions:display-dependency-updates

In Gradle, use:

1
./gradlew dependencyUpdates

This will show you if any of your dependencies are outdated and need to be updated to a compatible version.

Review Classpath Configuration

Ensure that your classpath is correctly configured to prioritize Flink’s bundled dependencies and avoid conflicts. This is particularly important if you are running Flink in a distributed environment, as the classpath needs to be consistent across all nodes in the cluster.

If you’re running Flink in standalone mode, make sure your job’s JAR file contains the correct dependencies, or use the Flink lib/ directory to place compatible versions of libraries.

Final Thoughts

The error java.lang.NoSuchMethodError: org.apache.commons.cli.CommandLine.hasOption in Flink is often caused by a version mismatch or classpath conflict related to Apache Commons CLI. To fix the issue:

  • Verify that the commons-cli jar package exists.
  • Ensure you’re using the correct version of Flink and Apache Commons CLI.
  • Exclude conflicting dependencies from your project.
  • Update your project’s dependencies to compatible versions.
  • Review your classpath to prevent conflicts at runtime.

By following these steps, you should be able to resolve the error and get your Flink application running smoothly again. If the problem persists, reviewing Flink’s official documentation or community forums might provide additional insights specific to your Flink version and environment.