{"record":{"id":"158f725205358825","repo":"temporalio/temporal","slug":"link-type-contains-invalid-char-valid-chars-alph","errorCode":null,"errorMessage":"link type contains invalid char (valid chars: alphanumeric, '_', '.', '/')","messagePattern":"link type contains invalid char \\(valid chars: alphanumeric, '_', '\\.', '/'\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/nexus/nexusrpc/api.go","lineNumber":248,"sourceCode":"\nfunc validateLinkURL(value *url.URL) error {\n\tif value == nil || value.String() == \"\" {\n\t\treturn errors.New(\"url is empty\")\n\t}\n\t_, err := url.ParseQuery(value.RawQuery)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"url query not percent-encoded: %s\", value)\n\t}\n\treturn nil\n}\n\nfunc validateLinkType(value string) error {\n\tif len(value) == 0 {\n\t\treturn errors.New(\"link type is empty\")\n\t}\n\tfor _, c := range value {\n\t\tif (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_' && c != '.' && c != '/' {\n\t\t\treturn errors.New(\"link type contains invalid char (valid chars: alphanumeric, '_', '.', '/')\")\n\t\t}\n\t}\n\treturn nil\n}\n\nvar durationRegexp = regexp.MustCompile(`^(\\d+(?:\\.\\d+)?)(ms|s|m)$`)\n\nfunc ParseDuration(value string) (time.Duration, error) {\n\tm := durationRegexp.FindStringSubmatch(value)\n\tif len(m) == 0 {\n\t\treturn 0, fmt.Errorf(\"invalid duration: %q\", value)\n\t}\n\tv, err := strconv.ParseFloat(m[1], 64)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\n\tswitch m[2] {","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/nexus/nexusrpc/api.go#L230-L266","documentation":"validateLinkType rejects link type strings containing characters outside [a-zA-Z0-9_.\\/] because link types appear in headers and routing keys where arbitrary characters are unsafe. encodeLink and decodeLink call it, so any Link whose Type contains spaces, hyphens, colons, or unicode characters fails with this error.","triggerScenarios":"Encoding or decoding a nexus Link whose Type contains an invalid character — e.g. Type set to 'my-service', 'com:example:Type', or any value with spaces or non-ASCII characters.","commonSituations":"Developers using hyphenated service names or colon-separated identifiers as link types; porting conventions from other systems that allow different separators; copy-pasted type names with trailing whitespace.","solutions":["Rewrite the link Type using only alphanumerics, '_', '.', or '/' (e.g. replace '-' with '_' or '.')","Sanitize/normalize the type string at the point where the link is constructed","Validate user- or config-supplied type names with the same character set before creating links"],"exampleFix":"// before\nlink.Type = \"my-service.Callback\"\n// after\nlink.Type = \"my_service.Callback\"","handlingStrategy":"validation","validationCode":"var linkTypeRe = regexp.MustCompile(`^[a-zA-Z0-9_./]+$`)\nfunc validLinkType(t string) bool { return linkTypeRe.MatchString(t) }","typeGuard":"if !linkTypeRe.MatchString(link.Type) { return fmt.Errorf(\"link type %q has invalid chars\", link.Type) }","tryCatchPattern":"if err := encodeLink(link); err != nil {\n    var invalid = strings.Contains(err.Error(), \"invalid char\")\n    // sanitize or reject\n}","preventionTips":["Sanitize externally supplied type names (replace '-', ':', spaces) before constructing links","Use '/' or '.' as separators instead of '-' or ':' in type names","Add a lint/test asserting all link types in the codebase match the charset regex"],"tags":["nexus","validation","input-validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}