apache/beam · error · IllegalArgumentException

TVF specified: + tvfName + is not found in the existing…

Error message

TVF specified: + tvfName + is not found in the existing TVF's: + foundNames

What it means

When SpannerIO is configured with a TVF (table-valued function) query, it queries INFORMATION_SCHEMA for the available TVFs and throws IllegalArgumentException if the requested tvfName is not among the found names. This fails fast at pipeline construction/expansion rather than at query time with a Spanner error.

Solutions

  1. Compare the tvfName in the message against the listed foundNames and fix the spelling/casing.
  2. Run SELECT tvf_name FROM INFORMATION_SCHEMA.TVFs (per dialect) against the configured database to list actual TVFs.
  3. Verify instanceId/databaseId in SpannerConfig point to the database where the TVF exists.
  4. Ensure quoting matches Spanner's rules (backticks for GoogleSQL) so the escaped name matches exactly.

Example fix

// before
SpannerRead.of(config).withQuery("SELECT * FROM TVF tvf_users(...)") // TVF 'tvf_users' typo
// after
SpannerRead.of(config).withQuery("SELECT * FROM TVF tvf_user_events(...)")
Defensive patterns

Strategy: validation

Validate before calling

// Before building the pipeline, verify the TVF exists
// SELECT tvf_name FROM INFORMATION_SCHEMA.TVFs — check tvfName is present
Set<String> tvfs = fetchTvfs(spannerConfig);
if (!tvfs.contains(tvfName)) throw new IllegalArgumentException("TVF missing: " + tvfName);

Try / catch

try { pipeline.apply(SpannerRead.of(config).withQuery(tvfSql)); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("TVF specified")) { /* correct name or deploy TVF */ } throw e; }

Prevention

When it happens

Trigger: Using SpannerRead.withQuery()/SpannerQuerySourceDef with a table-valued function whose quoted name is not present in the database's INFORMATION_SCHEMA.TVF list at pipeline build time.

Common situations: Typo in the TVF name; TVF created in a different database/project/instance; quoting differences (backticks/case) making the names not match; TVF dropped or not yet deployed to the target environment (e.g., pointing a staging pipeline at prod DB).

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerIO.java:3083

      }
      sql.append(")");
      Statement.Builder builder = Statement.newBuilder(sql.toString());
      for (int i = 0; i < quoteEscapedTvfNameList.size(); i++) {
        if (dialect == Dialect.POSTGRESQL) {
          builder.bind("p" + (i + 1)).to(quoteEscapedTvfNameList.get(i));
        } else {
          builder.bind("p" + i).to(quoteEscapedTvfNameList.get(i));
        }
      }
      Statement statement = builder.build();
      ResultSet resultSet = tx.executeQuery(statement);
      java.util.Set<String> foundNames = new java.util.HashSet<>();
      while (resultSet.next()) {
        foundNames.add(resultSet.getString(0));
      }
      for (String tvfName : quoteEscapedTvfNameList) {
        if (!foundNames.contains(tvfName)) {
          throw new IllegalArgumentException(
              "TVF specified: " + tvfName + " is not found in the existing TVF's: " + foundNames);
        }
      }
    }
  }

  @VisibleForTesting
  static boolean isMutableChangeStream(
      DatabaseClient databaseClient, Dialect dialect, String changeStreamName) {
    String fetchedPartitionMode = fetchPartitionMode(databaseClient, dialect, changeStreamName);
    if (fetchedPartitionMode.isEmpty()
        || fetchedPartitionMode.equalsIgnoreCase("IMMUTABLE_KEY_RANGE")) {
      return false;
    }
    return true;
  }

  private static String fetchPartitionMode(

View on GitHub (pinned to 12126d8942)