{"record":{"id":"60890bb1df0c3033","repo":"hashicorp/nomad","slug":"invalid-key-value-pair-for-topic-topic-s","errorCode":null,"errorMessage":"Invalid key value pair for topic, topic: %s","messagePattern":"Invalid key value pair for topic, topic: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"command/agent/event_endpoint.go","lineNumber":235,"sourceCode":"\n\tfor _, topic := range raw {\n\t\tk, v, err := parseTopic(topic)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing topics: %w\", err)\n\t\t}\n\n\t\ttopics[structs.Topic(k)] = append(topics[structs.Topic(k)], v)\n\t}\n\treturn topics, nil\n}\n\nfunc parseTopic(topic string) (string, string, error) {\n\tparts := strings.Split(topic, \":\")\n\t// infer wildcard if only given a topic\n\tif len(parts) == 1 {\n\t\treturn topic, \"*\", nil\n\t} else if len(parts) != 2 {\n\t\treturn \"\", \"\", fmt.Errorf(\"Invalid key value pair for topic, topic: %s\", topic)\n\t}\n\treturn parts[0], parts[1], nil\n}\n\nfunc allTopics() map[structs.Topic][]string {\n\treturn map[structs.Topic][]string{\"*\": {\"*\"}}\n}\n","sourceCodeStart":217,"sourceCodeEnd":243,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/command/agent/event_endpoint.go#L217-L243","documentation":"parseTopic expects each topic string to be either a bare topic name (wildcard '*' value inferred) or exactly key:value with a single colon. Any string with two or more colons — producing 3+ parts after strings.Split — is invalid and rejected with this message.","triggerScenarios":"Passing topic values like \"Deployment:eval-123:extra\" to parseEventTopics (from EventStream query params) — i.e., more than one ':' separator in a single topic query parameter.","commonSituations":"Appending filter keys that themselves contain colons; joining multiple topic filters into one parameter with colons; copy-pasting an event payload as the topic key.","solutions":["Remove extra colons; the key (topic name) must not contain ':'.","Emit multiple topic= parameters instead of combining into one.","Use the bare topic name without a value to get wildcard matching.","Validate topic strings client-side (one optional colon) before building the request."],"exampleFix":"// before\ntopic=Deployment:us-west:prod\n// after\ntopic=Deployment:us-west-prod","handlingStrategy":"validation","validationCode":"func validateTopicParam(topic string) error {\n  parts := strings.Split(topic, \":\")\n  if len(parts) > 2 {\n    return fmt.Errorf(\"topic %q must have at most one ':'\", topic)\n  }\n  return nil\n}","typeGuard":"func isWellFormedTopic(t string) bool {\n  parts := strings.Split(t, \":\")\n  return len(parts) == 1 || len(parts) == 2\n}","tryCatchPattern":"k, v, err := parseTopic(topic)\nif err != nil {\n  return fmt.Errorf(\"skip malformed topic %q: %w\", topic, err)\n}","preventionTips":["Sanitize topic keys to exclude ':' characters before building requests.","Wrap key:value payloads in URL-safe encodings (base64) or use separate parameters.","Document the key:value topic format for API consumers.","Unit-test topic parsers with colon-bearing inputs."],"tags":["events","parsing","validation"],"backgroundTag":"invalid-topic-format","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}