{"record":{"id":"d095267ddf099e16","repo":"apache/beam","slug":"tvf-specified-tvfname-is-not-found-in-the-existing-tvf-s","errorCode":null,"errorMessage":"TVF specified: + tvfName + is not found in the existing TVF's: + foundNames","messagePattern":"TVF specified: \\+ tvfName \\+ is not found in the existing TVF's: \\+ foundNames","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerIO.java","lineNumber":3083,"sourceCode":"      }\n      sql.append(\")\");\n      Statement.Builder builder = Statement.newBuilder(sql.toString());\n      for (int i = 0; i < quoteEscapedTvfNameList.size(); i++) {\n        if (dialect == Dialect.POSTGRESQL) {\n          builder.bind(\"p\" + (i + 1)).to(quoteEscapedTvfNameList.get(i));\n        } else {\n          builder.bind(\"p\" + i).to(quoteEscapedTvfNameList.get(i));\n        }\n      }\n      Statement statement = builder.build();\n      ResultSet resultSet = tx.executeQuery(statement);\n      java.util.Set<String> foundNames = new java.util.HashSet<>();\n      while (resultSet.next()) {\n        foundNames.add(resultSet.getString(0));\n      }\n      for (String tvfName : quoteEscapedTvfNameList) {\n        if (!foundNames.contains(tvfName)) {\n          throw new IllegalArgumentException(\n              \"TVF specified: \" + tvfName + \" is not found in the existing TVF's: \" + foundNames);\n        }\n      }\n    }\n  }\n\n  @VisibleForTesting\n  static boolean isMutableChangeStream(\n      DatabaseClient databaseClient, Dialect dialect, String changeStreamName) {\n    String fetchedPartitionMode = fetchPartitionMode(databaseClient, dialect, changeStreamName);\n    if (fetchedPartitionMode.isEmpty()\n        || fetchedPartitionMode.equalsIgnoreCase(\"IMMUTABLE_KEY_RANGE\")) {\n      return false;\n    }\n    return true;\n  }\n\n  private static String fetchPartitionMode(","sourceCodeStart":3065,"sourceCodeEnd":3101,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerIO.java#L3065-L3101","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Compare the tvfName in the message against the listed foundNames and fix the spelling/casing.","Run SELECT tvf_name FROM INFORMATION_SCHEMA.TVFs (per dialect) against the configured database to list actual TVFs.","Verify instanceId/databaseId in SpannerConfig point to the database where the TVF exists.","Ensure quoting matches Spanner's rules (backticks for GoogleSQL) so the escaped name matches exactly."],"exampleFix":"// before\nSpannerRead.of(config).withQuery(\"SELECT * FROM TVF tvf_users(...)\") // TVF 'tvf_users' typo\n// after\nSpannerRead.of(config).withQuery(\"SELECT * FROM TVF tvf_user_events(...)\")","handlingStrategy":"validation","validationCode":"// Before building the pipeline, verify the TVF exists\n// SELECT tvf_name FROM INFORMATION_SCHEMA.TVFs — check tvfName is present\nSet<String> tvfs = fetchTvfs(spannerConfig);\nif (!tvfs.contains(tvfName)) throw new IllegalArgumentException(\"TVF missing: \" + tvfName);","typeGuard":null,"tryCatchPattern":"try { pipeline.apply(SpannerRead.of(config).withQuery(tvfSql)); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith(\"TVF specified\")) { /* correct name or deploy TVF */ } throw e; }","preventionTips":["List existing TVFs with INFORMATION_SCHEMA.TVFs before referencing one.","Keep TVF DDL migrations applied to every environment the pipeline targets.","Match Spanner quoting rules exactly (backticks for GoogleSQL identifiers)."],"tags":["java","beam","spanner","tvf","resource-not-found"],"backgroundTag":"resource-not-found","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}