apache/beam · error · IllegalArgumentException
Pubsub topic is not in projects/
Error message
Pubsub topic is not in projects/<project_id>/topics/<topic_name> format: {path} What it means
PubsubIO.Read.fromPath requires the topic path to match projects/<project_id>/topics/<topic_name>. If neither the modern nor legacy v1beta1 pattern matches TOPIC_REGEXP, this IllegalArgumentException is thrown describing the expected format.
Solutions
- Use the fully qualified path: projects/YOUR_PROJECT/topics/YOUR_TOPIC.
- Confirm you aren't passing a subscription path to fromTopic (use fromSubscription instead).
- Build the path programmatically: String.format("projects/%s/topics/%s", projectId, topicId).
Example fix
// before
PubsubIO.readStrings().fromTopic("events");
// after
PubsubIO.readStrings().fromTopic("projects/my-project/topics/events"); Defensive patterns
Strategy: validation
Validate before calling
static void checkTopicPath(String path) {
if (!path.matches("projects/[a-zA-Z0-9-_.~%+]+/topics/[a-zA-Z0-9-_.~%+]+"))
throw new IllegalArgumentException("Expected projects/<proj>/topics/<name>: " + path);
} Type guard
boolean isTopicPath(String p) {
return p != null && p.matches("projects/[^/]+/topics/[^/]+");
} Try / catch
try {
return PubsubIO.readStrings().fromTopic(topic);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("topics/<topic_name> format"))
throw new ConfigException("Topic path must be projects/<proj>/topics/<name>, got: " + topic, e);
throw e;
} Prevention
- Keep full topic paths in configuration
- Use a builder helper: topicPath(project, topic)
- Don't confuse fromTopic with fromSubscription arguments
When it happens
Trigger: Calling PubsubIO.read...().fromTopic()/fromPath with a bare topic name ("mytopic"), a subscription path (projects/p/subscriptions/s), or a malformed path.
Common situations: Passing only the topic short name from configuration; accidentally passing the subscription path to fromTopic; typos in the 'topics' segment.
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.
Related errors
- Pubsub subscription is not in projects/
- Can't set both the topic and the subscription for a…
- Cannot get data catalog name for malformed topic path
- Could not parse Pub/Sub message
- Illegal Pubsub object name specified
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/3b9300d8be1477a7.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubIO.java:483
*/
public static PubsubTopic fromPath(String path) {
if (path.equals(TOPIC_DEV_NULL_TEST_NAME)) {
return new PubsubTopic(PubsubTopic.Type.FAKE, "", path);
}
String projectName, topicName;
Matcher v1beta1Match = V1BETA1_TOPIC_REGEXP.matcher(path);
if (v1beta1Match.matches()) {
LOG.warn(
"Saw topic in v1beta1 format. Topics should be in the format "
+ "projects/<project_id>/topics/<topic_name>");
projectName = v1beta1Match.group(1);
topicName = v1beta1Match.group(2);
} else {
Matcher match = TOPIC_REGEXP.matcher(path);
if (!match.matches()) {
throw new IllegalArgumentException(
"Pubsub topic is not in projects/<project_id>/topics/<topic_name> format: " + path);
}
projectName = match.group(1);
topicName = match.group(2);
}
projectName =
checkArgumentNotNull(
projectName, "Invalid path: project name must be non-null: %s", path);
topicName =
checkArgumentNotNull(topicName, "Invalid path: topic name must be non-null: %s", path);
validateProjectName(projectName);
validatePubsubName(topicName);
return new PubsubTopic(PubsubTopic.Type.NORMAL, projectName, topicName);
}
/**View on GitHub (pinned to 12126d8942)