apache/beam · warning
Cannot get data catalog name for malformed topic path
Error message
Cannot get data catalog name for malformed topic path {}. Expected format: projects/<project>/topics/<topic> What it means
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.
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.
Example fix
// before
String badPath = "my-topic";
client.getDataCatalogSegments(badPath);
// after
String goodPath = PubsubClient.topicPathFromName("my-project", "my-topic");
// -> projects/my-project/topics/my-topic Defensive patterns
Strategy: validation
Validate before calling
static boolean isWellFormedTopicPath(String p) {
return p != null && p.matches("projects/[^/]+/topics/[^/]+");
} Type guard
String requireTopicPath(String p) {
if (p == null || !p.matches("projects/[^/]+/topics/[^/]+"))
throw new IllegalArgumentException("topic path must be projects/<project>/topics/<topic>: " + p);
return p;
} Try / catch
// No exception thrown; check the returned list before use:
List<String> segs = client.getDataCatalogSegments(path);
if (segs.isEmpty()) { throw new IllegalArgumentException("malformed topic path: " + path); } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Pubsub subscription is not in projects/
- Pubsub topic is not in projects/
- Saw subscription in v1beta1 format. Subscriptions should be…
- A schema was provided without a data format (or viceversa)…
- Bigtable location must be in the following format…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/c5287f231c0d703b.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubClient.java:329
List<String> splits = Splitter.on('/').splitToList(path);
checkState(splits.size() == 4, "Malformed topic path %s", path);
return splits.get(3);
}
/**
* Returns the data catalog segments. This method is fail-safe. If topic path is malformed, it
* returns an empty string.
*/
public List<String> getDataCatalogSegments() {
List<String> splits = Splitter.on('/').splitToList(path);
if (splits.size() == 4) {
// well-formed path
return ImmutableList.of(splits.get(1), splits.get(3));
} else {
// Mal-formed path. It is either a test fixture or user error and will fail on publish.
// We do not throw exception instead return empty string here.
LOG.warn(
"Cannot get data catalog name for malformed topic path {}. Expected format: "
+ "projects/<project>/topics/<topic>",
path);
return ImmutableList.of();
}
}
public String getFullPath() {
List<String> splits = Splitter.on('/').splitToList(path);
checkState(splits.size() == 4, "Malformed topic path %s", path);
return String.format("/topics/%s/%s", splits.get(1), splits.get(3));
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}View on GitHub (pinned to 12126d8942)