{"record":{"id":"c5287f231c0d703b","repo":"apache/beam","slug":"cannot-get-data-catalog-name-for-malformed-topic-path","errorCode":null,"errorMessage":"Cannot get data catalog name for malformed topic path {}. Expected format: projects/<project>/topics/<topic>","messagePattern":"Cannot get data catalog name for malformed topic path (.+?)\\. Expected format: projects/<project>/topics/<topic>","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubClient.java","lineNumber":329,"sourceCode":"      List<String> splits = Splitter.on('/').splitToList(path);\n\n      checkState(splits.size() == 4, \"Malformed topic path %s\", path);\n      return splits.get(3);\n    }\n\n    /**\n     * Returns the data catalog segments. This method is fail-safe. If topic path is malformed, it\n     * returns an empty string.\n     */\n    public List<String> getDataCatalogSegments() {\n      List<String> splits = Splitter.on('/').splitToList(path);\n      if (splits.size() == 4) {\n        // well-formed path\n        return ImmutableList.of(splits.get(1), splits.get(3));\n      } else {\n        // Mal-formed path. It is either a test fixture or user error and will fail on publish.\n        // We do not throw exception instead return empty string here.\n        LOG.warn(\n            \"Cannot get data catalog name for malformed topic path {}. Expected format: \"\n                + \"projects/<project>/topics/<topic>\",\n            path);\n        return ImmutableList.of();\n      }\n    }\n\n    public String getFullPath() {\n      List<String> splits = Splitter.on('/').splitToList(path);\n      checkState(splits.size() == 4, \"Malformed topic path %s\", path);\n      return String.format(\"/topics/%s/%s\", splits.get(1), splits.get(3));\n    }\n\n    @Override\n    public boolean equals(@Nullable Object o) {\n      if (this == o) {\n        return true;\n      }","sourceCodeStart":311,"sourceCodeEnd":347,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubClient.java#L311-L347","documentation":"PubsubClient.getDataCatalogSegments parses a topic path to extract project and topic name segments for Data Catalog lineage. When the path does not have the well-formed projects/<project>/topics/<topic> shape (path split does not yield 4 segments), it logs a warning and returns an empty list instead of throwing, since the malformed path will fail later at publish time anyway.","triggerScenarios":"Calling getDataCatalogSegments (directly or via topicPathFromPath / apply) with a topic path like 'my-topic', 'projects/p/topics/' (trailing empty segment), or a test fixture path that lacks the full 4-segment structure.","commonSituations":"Unit tests using short fake topic names; user-supplied topic strings missing the full resource path; accidentally passing a subscription path or topic short-name where a fully-qualified topic path is expected.","solutions":["Pass a fully-qualified topic path: projects/<project>/topics/<topic>.","Use PubsubClient.topicPathFromName(project, topic) to construct a valid path from components.","If this is a test fixture, either ignore the warning or supply a well-formed fake path to keep lineage parsing quiet.","Check the path value at the call site (apply/topicPathFromNameWellFormed) for typos or truncated project IDs."],"exampleFix":"// before\nString badPath = \"my-topic\";\nclient.getDataCatalogSegments(badPath);\n// after\nString goodPath = PubsubClient.topicPathFromName(\"my-project\", \"my-topic\");\n// -> projects/my-project/topics/my-topic","handlingStrategy":"validation","validationCode":"static boolean isWellFormedTopicPath(String p) {\n  return p != null && p.matches(\"projects/[^/]+/topics/[^/]+\");\n}","typeGuard":"String requireTopicPath(String p) {\n  if (p == null || !p.matches(\"projects/[^/]+/topics/[^/]+\"))\n    throw new IllegalArgumentException(\"topic path must be projects/<project>/topics/<topic>: \" + p);\n  return p;\n}","tryCatchPattern":"// No exception thrown; check the returned list before use:\nList<String> segs = client.getDataCatalogSegments(path);\nif (segs.isEmpty()) { throw new IllegalArgumentException(\"malformed topic path: \" + path); }","preventionTips":["Build paths via topicPathFromName(project, topic) instead of string concatenation.","Validate user-supplied topic strings against projects/<project>/topics/<topic> at config load.","Never pass subscription paths or short topic names to topic-path APIs.","Avoid short fake names in tests; use well-formed fixture paths."],"tags":["java","pubsub","url-format","data-catalog","lineage"],"backgroundTag":"invalid-url-format","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"}