apache/beam · critical · java.lang.RuntimeException

Unable to convert pipeline options, please check for…

Error message

Unable to convert pipeline options, please check for outdated jackson-core version in the classpath.

What it means

PipelineOptionsTranslation.toProto serializes PipelineOptions to JSON with Jackson and requires the resulting object to have at least one 'options' entry; mandatory options make an empty map impossible when Jackson works correctly. An empty fields() iterator indicates an incompatible/outdated jackson-core (observed with 2.2.3) silently producing wrong output, so Beam fails fast with this RuntimeException.

Solutions

  1. Run 'mvn dependency:tree' (or Gradle dependencies) and force jackson-core to the Beam-managed version, excluding stale transitive versions
  2. Check the runtime classpath/jar for duplicate jackson-core jars and remove outdated ones
  3. Add an explicit jackson-core dependency pinned to the Beam BOM version

Example fix

// before (pom.xml)
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.2.3</version></dependency>
// after
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.16.1</version></dependency>
Defensive patterns

Strategy: validation

Validate before calling

String version = com.fasterxml.jackson.core.json.PackageVersion.VERSION.toString();
if (version.compareTo("2.14") < 0) throw new IllegalStateException("jackson-core too old: " + version);

Try / catch

try { Struct s = PipelineOptionsTranslation.toProto(options); } catch (RuntimeException e) { if (e.getMessage().contains("jackson-core")) throw new IllegalStateException("Fix jackson-core version on classpath", e); throw e; }

Prevention

When it happens

Trigger: Calling PipelineOptionsTranslation.toProto/toJson when the classpath contains an old jackson-core (e.g. 2.2.3) that mis-serializes the options object into an empty root.

Common situations: Dependency conflicts pulling an ancient jackson-core transitively; fat jars bundling multiple Jackson versions; shaded/classloader environments resolving the wrong Jackson class.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/ef078db4dfe5d056. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/PipelineOptionsTranslation.java:63

  public static final String PIPELINE_OPTIONS_URN_PREFIX = "beam:option:";
  public static final String PIPELINE_OPTIONS_URN_SUFFIX = ":v1";

  /** Converts the provided {@link PipelineOptions} to a {@link Struct}. */
  public static Struct toProto(PipelineOptions options) {
    Struct.Builder builder = Struct.newBuilder();

    try {
      // TODO: Officially define URNs for options and their scheme.
      JsonNode treeNode = MAPPER.valueToTree(options);
      JsonNode rootOptions = treeNode.get("options");
      Iterator<Map.Entry<String, JsonNode>> optionsEntries = rootOptions.fields();

      if (!optionsEntries.hasNext()) {
        // Due to mandatory options there is no way this map can be empty.
        // If it is, then fail fast as it is due to incompatible jackson-core in the classpath.
        // (observed with version 2.2.3)
        throw new RuntimeException(
            "Unable to convert pipeline options, please check for outdated jackson-core version in the classpath.");
      }

      Map<String, TreeNode> optionsUsingUrns = new HashMap<>();
      while (optionsEntries.hasNext()) {
        Map.Entry<String, JsonNode> entry = optionsEntries.next();
        optionsUsingUrns.put(
            PIPELINE_OPTIONS_URN_PREFIX
                + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey())
                + PIPELINE_OPTIONS_URN_SUFFIX,
            entry.getValue());
      }

      // The JSON format of a Protobuf Struct is the JSON object that is equivalent to that struct
      // (with values encoded in a standard json-codeable manner). See Beam PR 3719 for more.
      JsonFormat.parser().merge(MAPPER.writeValueAsString(optionsUsingUrns), builder);
      return builder.build();
    } catch (IOException e) {

View on GitHub (pinned to 12126d8942)