{"record":{"id":"d27dcef823bd92e8","repo":"nats-io/nats-server","slug":"stream-subject-transform-from-s-to-s-w","errorCode":null,"errorMessage":"stream subject transform from '%s' to '%s': %w","messagePattern":"stream subject transform from '(.+?)' to '(.+?)': %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/stream.go","lineNumber":1053,"sourceCode":"\t\t// protection: sa.Created is immutable.\n\t\tmset.created = sa.Created\n\t}\n\n\t// Start our signaling routine to process consumers.\n\tmset.sigq = newIPQueue[*cMsg](s, qpfx+\"obs\") // of *cMsg\n\tgo mset.signalConsumersLoop()\n\n\t// For no-ack consumers when we are interest retention.\n\tif cfg.Retention != LimitsPolicy {\n\t\tmset.ackq = newIPQueue[uint64](s, qpfx+\"acks\")\n\t}\n\n\t// Check for input subject transform\n\tif cfg.SubjectTransform != nil {\n\t\ttr, err := NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination)\n\t\tif err != nil {\n\t\t\tjsa.mu.Unlock()\n\t\t\treturn nil, fmt.Errorf(\"stream subject transform from '%s' to '%s': %w\", cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination, err)\n\t\t}\n\t\tmset.itr = tr\n\t}\n\n\t// Check for RePublish.\n\tif cfg.RePublish != nil {\n\t\ttr, err := NewSubjectTransform(cfg.RePublish.Source, cfg.RePublish.Destination)\n\t\tif err != nil {\n\t\t\tjsa.mu.Unlock()\n\t\t\treturn nil, fmt.Errorf(\"stream republish transform from '%s' to '%s': %w\", cfg.RePublish.Source, cfg.RePublish.Destination, err)\n\t\t}\n\t\t// Assign our transform for republishing.\n\t\tmset.tr = tr\n\t}\n\tstoreDir := filepath.Join(jsa.storeDir, streamsDir, cfg.Name)\n\tjsa.mu.Unlock()\n\n\t// Bind to the user account.","sourceCodeStart":1035,"sourceCodeEnd":1071,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/stream.go#L1035-L1071","documentation":"Stream-creation validation: the stream-level cfg.SubjectTransform could not be constructed via NewSubjectTransform(source, destination); the input transform on the stream config is invalid (bad subject syntax, illegal wildcards in source/destination mapping). The offending pair and the transform error are wrapped in the message.","triggerScenarios":"AddStream with cfg.SubjectTransform whose Source/Destination pair is invalid: token-count mismatch, illegal wildcard usage, or invalid characters in either subject.","commonSituations":"Remapping all messages published to a stream into a different subject space; typical mistake is destination with more tokens than source or wildcards in the wrong token position.","solutions":["Align the destination's token structure with the source (each wildcard maps one token).","Check both subjects with IsValidSubject and test with NewSubjectTransform before calling AddStream.","Remove cfg.SubjectTransform if no stream-wide remap is intended."],"exampleFix":"// before\nSubjectTransform: &SubjectTransformConfig{Source: \"events.*\", Destination: \"archive.events.*.v2\"}\n// after\nSubjectTransform: &SubjectTransformConfig{Source: \"events.*\", Destination: \"archive.events.*\"}","handlingStrategy":"validation","validationCode":"if cfg.SubjectTransform != nil {\n  if _, err := server.NewSubjectTransform(cfg.SubjectTransform.Source, cfg.SubjectTransform.Destination); err != nil { return err }\n}","typeGuard":null,"tryCatchPattern":"_, err := js.AddStream(cfg)\nif err != nil && strings.Contains(err.Error(), \"stream subject transform\") { /* fix transform, resubmit */ }","preventionTips":["Keep the stream-wide transform structurally simple (same token count, 1:1 wildcard mapping).","Test with NewSubjectTransform locally before creating the stream."],"tags":["jetstream","stream","subject-transform","validation"],"backgroundTag":"subject-transform-invalid-mapping","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}