nats-io/nats-server · error

stream republish transform from '%s' to '%s': %w

Error message

stream republish transform from '%s' to '%s': %w

What it means

This error wraps a failure from NewSubjectTransform when a stream's RePublish configuration contains a subject transform that cannot be built. The server rejects stream creation/update rather than starting a stream whose republishing would silently drop or misroute messages. The wrapped error identifies the specific problem with the Source or Destination subject.

Source

Thrown at server/stream.go:1063

		mset.ackq = newIPQueue[uint64](s, qpfx+"acks")
	}

	// Check for input subject transform
	if cfg.SubjectTransform != nil {
		tr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)
		if err != nil {
			jsa.mu.Unlock()
			return nil, fmt.Errorf("stream subject transform from '%s' to '%s': %w", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err)
		}
		mset.itr = tr
	}

	// Check for RePublish.
	if cfg.RePublish != nil {
		tr, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination)
		if err != nil {
			jsa.mu.Unlock()
			return nil, fmt.Errorf("stream republish transform from '%s' to '%s': %w", cfg.RePublish.Source, cfg.RePublish.Destination, err)
		}
		// Assign our transform for republishing.
		mset.tr = tr
	}
	storeDir := filepath.Join(jsa.storeDir, streamsDir, cfg.Name)
	jsa.mu.Unlock()

	// Bind to the user account.
	c.registerWithAccount(a)
	// Bind to the system account.
	ic.registerWithAccount(s.SystemAccount())

	// Create the appropriate storage
	fsCfg := fsConfig
	if fsCfg == nil {
		fsCfg = &FileStoreConfig{}
		// If we are file based and not explicitly configured
		// we may be able to auto-tune based on max msgs or bytes.

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Fix the RePublish.Source subject so it is a valid NATS subject (no spaces, wildcard rules respected).
  2. Ensure RePublish.Destination wildcard tokens only reference tokens present in the Source (e.g. Source 'foo.*.bar' -> Destination 'baz.*' not 'baz.>').
  3. Print the wrapped %w error to see the exact subject-transform failure from NewSubjectTransform.
  4. Test subject strings with a validator before assigning them to cfg.RePublish.

Example fix

// before
cfg := jetstream.StreamConfig{
  Name: "ORDERS",
  RePublish: &jetstream.RePublish{Source: "orders..", Destination: "rep.>"},
}
// after
cfg := jetstream.StreamConfig{
  Name: "ORDERS",
  RePublish: &jetstream.RePublish{Source: "orders.*", Destination: "rep.orders"},
}
Defensive patterns

Strategy: validation

Validate before calling

func validRepublish(rp *jetstream.RePublish) error {
  if rp == nil { return nil }
  for _, s := range []string{rp.Source, rp.Destination} {
    if s == "" || strings.ContainsAny(s, " \t") { return fmt.Errorf("invalid subject %q", s) }
  }
  srcTok := strings.Split(rp.Source, ".")
  for i, t := range strings.Split(rp.Destination, ".") {
    if (t == "*" || t == ">") && (i >= len(srcTok) || (srcTok[i] != "*" && srcTok[i] != ">")) {
      return fmt.Errorf("destination wildcard at %d has no source counterpart", i)
    }
  }
  return nil
}

Type guard

func hasRepublish(cfg jetstream.StreamConfig) bool { return cfg.RePublish != nil }

Prevention

When it happens

Trigger: Calling StreamConfig.AddStream (or updating) with cfg.RePublish set to a RePublish{Source, Destination} whose Source is an invalid subject (wildcards misplaced, tokens >1 char) or whose Destination is not a valid transform target (e.g. contains wildcard tokens the Source does not provide).

Common situations: Typos in republish subjects; using '*' or '>' in the Destination that the Source doesn't supply; copy-pasting subjects with spaces; constructing subjects dynamically from user input; NATS server version differences in transform validation rules.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/818b030afec96277. Report an issue: GitHub.