temporalio/temporal · error

link type contains invalid char (valid chars: alphanumeric,

Error message

link type contains invalid char (valid chars: alphanumeric, '_', '.', '/')

What it means

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.

Source

Thrown at common/nexus/nexusrpc/api.go:248

func validateLinkURL(value *url.URL) error {
	if value == nil || value.String() == "" {
		return errors.New("url is empty")
	}
	_, err := url.ParseQuery(value.RawQuery)
	if err != nil {
		return fmt.Errorf("url query not percent-encoded: %s", value)
	}
	return nil
}

func validateLinkType(value string) error {
	if len(value) == 0 {
		return errors.New("link type is empty")
	}
	for _, c := range value {
		if (c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c < '0' || c > '9') && c != '_' && c != '.' && c != '/' {
			return errors.New("link type contains invalid char (valid chars: alphanumeric, '_', '.', '/')")
		}
	}
	return nil
}

var durationRegexp = regexp.MustCompile(`^(\d+(?:\.\d+)?)(ms|s|m)$`)

func ParseDuration(value string) (time.Duration, error) {
	m := durationRegexp.FindStringSubmatch(value)
	if len(m) == 0 {
		return 0, fmt.Errorf("invalid duration: %q", value)
	}
	v, err := strconv.ParseFloat(m[1], 64)
	if err != nil {
		return 0, err
	}

	switch m[2] {

View on GitHub (pinned to bde624efd1)

Solutions

  1. Rewrite the link Type using only alphanumerics, '_', '.', or '/' (e.g. replace '-' with '_' or '.')
  2. Sanitize/normalize the type string at the point where the link is constructed
  3. Validate user- or config-supplied type names with the same character set before creating links

Example fix

// before
link.Type = "my-service.Callback"
// after
link.Type = "my_service.Callback"
Defensive patterns

Strategy: validation

Validate before calling

var linkTypeRe = regexp.MustCompile(`^[a-zA-Z0-9_./]+$`)
func validLinkType(t string) bool { return linkTypeRe.MatchString(t) }

Type guard

if !linkTypeRe.MatchString(link.Type) { return fmt.Errorf("link type %q has invalid chars", link.Type) }

Try / catch

if err := encodeLink(link); err != nil {
    var invalid = strings.Contains(err.Error(), "invalid char")
    // sanitize or reject
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of temporalio/temporal@bde624efd1 (2026-09-01). Data as JSON: /api/errors/158f725205358825. Report an issue: GitHub.