apache/beam · error · RuntimeException

Failed to parse row filter text proto

Error message

Failed to parse row filter text proto

What it means

BigtableIO.Read allows a RowFilter to be supplied as a text-format protobuf string via BigtableReadOptions.getRowFilterTextProto(). When TextFormat.parse fails on that string, a RuntimeException('Failed to parse row filter text proto') is thrown with the ParseException as cause. The string must be a valid text-encoding of a google.bigtable.v2.RowFilter.

Solutions

  1. Read the wrapped TextFormat.ParseException cause — it names the exact line/syntax problem
  2. Validate the string by parsing locally: TextFormat.parse(text, RowFilter.class) in a unit test
  3. Build the filter programmatically with RowFilter.newBuilder() and print with TextFormat.printer() to generate a known-valid string
  4. Escape special characters in regex/bytes fields per text-proto rules (e.g. quoted strings)

Example fix

// before
.withRowFilterTextProto("family_regex = 'stats.*'")
// after
.withRowFilterTextProto("family_regex: 'stats.*'")
Defensive patterns

Strategy: validation

Validate before calling

String text = rowFilterTextProto.get();
try {
  TextFormat.parse(text, com.google.bigtable.v2.RowFilter.class); // throws if invalid
} catch (TextFormat.ParseException e) {
  throw new IllegalArgumentException("Invalid RowFilter text proto: " + e.getMessage(), e);
}

Try / catch

try {
  BigtableIO.read().withBigtableOptions(opts).withRowFilterTextProto(text).expand(...);
} catch (RuntimeException e) {
  if (e.getCause() instanceof TextFormat.ParseException) {
    // fix the text proto syntax named in the cause
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling BigtableIO.read().withRowFilterTextProto(...) (or setting the pipeline option) with a string that is not valid text-proto: bad field names, missing escapes, invalid syntax, or wrong message nesting.

Common situations: Hand-written filter strings with typos, filters copied in wrong syntax (e.g. JSON instead of text proto), passing a regex with unescaped characters, forgetting to nest fields like chain { filters { ... } } correctly.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigtable/BigtableIO.java:1971

      return readOptions;
    }

    public List<ByteKeyRange> getRanges() {
      return readOptions.getKeyRanges().get();
    }

    public @Nullable RowFilter getRowFilter() {
      RowFilter.Chain.Builder chain = RowFilter.Chain.newBuilder();
      ValueProvider<RowFilter> rowFilterValueProvider = readOptions.getRowFilter();
      if (rowFilterValueProvider != null && rowFilterValueProvider.isAccessible()) {
        chain.addFilters(rowFilterValueProvider.get());
      }
      ValueProvider<String> textFilterValueProvider = readOptions.getRowFilterTextProto();
      if (textFilterValueProvider != null && textFilterValueProvider.isAccessible()) {
        try {
          chain.addFilters(TextFormat.parse(textFilterValueProvider.get(), RowFilter.class));
        } catch (TextFormat.ParseException e) {
          throw new RuntimeException("Failed to parse row filter text proto", e);
        }
      }

      switch (chain.getFiltersCount()) {
        case 0:
          return null;
        case 1:
          return chain.getFilters(0);
        default:
          return RowFilter.newBuilder().setChain(chain.build()).build();
      }
    }

    public @Nullable Integer getMaxBufferElementCount() {
      return readOptions.getMaxBufferElementCount();
    }

    public ValueProvider<String> getTableId() {

View on GitHub (pinned to 12126d8942)