temporalio/temporal · error

invalid config type: %T for nexusoperation.callback.endpoint

Error message

invalid config type: %T for nexusoperation.callback.endpoint.template, expected string

What it means

The dynamicconfig global setting 'nexusoperation.callback.endpoint.template' is declared with a typed-converter that only accepts a string, which is parsed as a Go text/template used to build Nexus callback URLs. If the configured value is not a string, the converter fails with this error, breaking any code path that reads the setting.

Source

Thrown at chasm/lib/nexusoperation/config.go:166

		headers.PrincipalNameHeaderName,
	},
	`Case insensitive list of disallowed header keys for Nexus Operations. ScheduleNexusOperation commands with a
"nexus_header" field that contains any of these disallowed keys will be rejected.`,
)

var MaxOperationScheduleToCloseTimeout = dynamicconfig.NewNamespaceDurationSetting(
	"nexusoperation.limit.scheduleToCloseTimeout",
	0,
	`Maximum allowed duration of a Nexus Operation. ScheduleOperation commands that specify no schedule-to-close timeout
or a longer timeout than permitted will have their schedule-to-close timeout capped to this value. 0 implies no limit.`,
)

var CallbackURLTemplate = dynamicconfig.NewGlobalTypedSettingWithConverter(
	"nexusoperation.callback.endpoint.template",
	func(in any) (*template.Template, error) {
		s, ok := in.(string)
		if !ok {
			return nil, fmt.Errorf("invalid config type: %T for nexusoperation.callback.endpoint.template, expected string", in)
		}
		if s == "unset" {
			return nil, nil
		}
		return template.New("NexusCallbackURL").Parse(s)
	},
	nil,
	`Controls the template for generating callback URLs included in Nexus operation requests, which are used to deliver
asynchronous completion for external endpoint targets. The template can be used to interpolate the {{.NamepaceName}}
and {{.NamespaceID}} parameters to construct a publicly accessible URL.
Must be set to call external endpoints.`,
)

type RetryPolicyConfig struct {
	InitialInterval time.Duration
	MaxInterval     time.Duration
}

View on GitHub (pinned to bde624efd1)

Solutions

  1. Quote the value in dynamic config so it is a Go string, e.g. nexusoperation.callback.endpoint.template: "http://localhost:7243/namespaces/{{.Namespace}}/nexus/callbacks"
  2. If dynamic config is a YAML/JSON file, ensure the entry is a scalar string, not a number/bool/nested object
  3. Validate the template parses correctly (template.New(...).Parse) before deploying the config

Example fix

# before
nexusoperation.callback.endpoint.template: {"url": "http://host/cb"}
# after
nexusoperation.callback.endpoint.template: "http://host/cb"
Defensive patterns

Strategy: validation

Validate before calling

v, ok := cfg.Get("nexusoperation.callback.endpoint.template")
if _, ok := v.(string); !ok {
    return fmt.Errorf("nexusoperation.callback.endpoint.template must be a string, got %T", v)
}
if _, err := template.New("NexusCallbackURL").Parse(v.(string)); err != nil {
    return fmt.Errorf("template parse failed: %w", err)
}

Type guard

func isStringSetting(v any) (string, bool) {
    s, ok := v.(string)
    return s, ok
}

Prevention

When it happens

Trigger: Setting nexusoperation.callback.endpoint.template in dynamic config (file, DB, or runtime) to a non-string value — e.g. a JSON/YAML number, boolean, object, or map — then any code reading the setting (e.g. during Nexus operation start) invokes the converter and gets this error.

Common situations: Config file has the value unquoted (YAML parses it as a non-string), or a runtime-config UI stores a non-string type. Also happens when someone configures the raw template in a structured config format that coerces types.

Related errors


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