Files
natsdotnet/gaps/utilities-and-other.md
Joseph Doherty c30e67a69d Fix E2E test gaps and add comprehensive E2E + parity test suites
- Fix pull consumer fetch: send original stream subject in HMSG (not inbox)
  so NATS client distinguishes data messages from control messages
- Fix MaxAge expiry: add background timer in StreamManager for periodic pruning
- Fix JetStream wire format: Go-compatible anonymous objects with string enums,
  proper offset-based pagination for stream/consumer list APIs
- Add 42 E2E black-box tests (core messaging, auth, TLS, accounts, JetStream)
- Add ~1000 parity tests across all subsystems (gaps closure)
- Update gap inventory docs to reflect implementation status
2026-03-12 14:09:23 -04:00

48 KiB

Utilities & Other — Gap Analysis

This file tracks what has and hasn't been ported from Go to .NET for the Utilities & Other module. See stillmissing.md for the full LOC comparison across all modules.

LLM Instructions: How to Analyze This Category

Step 1: Read the Go Reference Files

Read each Go source file listed below. For every file:

  1. Extract all exported types (structs, interfaces, type aliases)
  2. Extract all exported methods on those types (receiver functions)
  3. Extract all exported standalone functions
  4. Note key constants, enums, and protocol states
  5. Note important unexported helpers that implement core logic (functions >20 lines)
  6. Pay attention to concurrency patterns (goroutines, mutexes, channels) — these map to different .NET patterns

Step 2: Read the .NET Implementation Files

Read all .cs files in the .NET directories listed below. For each Go symbol found in Step 1:

  1. Search for a matching type, method, or function in .NET
  2. If found, compare the behavior: does it handle the same edge cases? Same error paths?
  3. If partially implemented, note what's missing
  4. If not found, note it as MISSING

Step 3: Cross-Reference Tests

Compare Go test functions against .NET test methods:

  1. For each Go Test* function, check if a corresponding .NET [Fact] or [Theory] exists
  2. Note which test scenarios are covered and which are missing
  3. Check the parity DB (docs/test_parity.db) for existing mappings:
    sqlite3 docs/test_parity.db "SELECT go_test, dotnet_test, confidence FROM test_mappings tm JOIN go_tests gt ON tm.go_test_id=gt.rowid JOIN dotnet_tests dt ON tm.dotnet_test_id=dt.rowid WHERE gt.go_file LIKE '%PATTERN%'"
    

Step 4: Classify Each Item

Use these status values:

Status Meaning
PORTED Equivalent exists in .NET with matching behavior
PARTIAL .NET implementation exists but is incomplete (missing edge cases, error handling, or features)
MISSING No .NET equivalent found — needs to be ported
NOT_APPLICABLE Go-specific pattern that doesn't apply to .NET (build tags, platform-specific goroutine tricks, etc.)
DEFERRED Intentionally skipped for now (document why)

Step 5: Fill In the Gap Inventory

Add rows to the Gap Inventory table below. Group by Go source file. Include the Go file and line number so a porting LLM can jump directly to the reference implementation.

Key Porting Notes for Utilities & Other

  • This category is at 7% LOC parity — significant gap, but many items may be NOT_APPLICABLE:
    • sendq.go / ipqueue.go — Go channel-based patterns; .NET uses Channel<T> or different buffering
    • ring.go — May be replaced by .NET collections
    • ats/ — Address translation for NAT environments
    • elastic/ — Elasticsearch metric export (may be deferred)
    • tpm/ — Trusted Platform Module integration (platform-specific, likely DEFERRED)
    • internal/fastrand — Go's fast random; .NET has Random.Shared
    • internal/ldap — LDAP DN parsing for LDAP auth
    • internal/antithesis — Chaos testing assertions (NOT_APPLICABLE unless using Antithesis)
  • Focus on: util.go (byte parsing helpers), errors.go (error definitions), rate_counter.go, scheduler.go.

Go Reference Files (Source)

  • golang/nats-server/server/util.go — General utilities (string helpers, byte parsing, etc.)
  • golang/nats-server/server/ring.go — Ring buffer implementation
  • golang/nats-server/server/rate_counter.go — Rate limiting / counting
  • golang/nats-server/server/sendq.go — Send queue for outbound messages
  • golang/nats-server/server/ipqueue.go — IP-based queue
  • golang/nats-server/server/errors.go — Error type definitions
  • golang/nats-server/server/errors_gen.go — Generated error codes
  • golang/nats-server/server/sdm.go — Server dynamic management
  • golang/nats-server/server/scheduler.go — Internal task scheduler
  • golang/nats-server/server/ats/ats.go — Address translation service
  • golang/nats-server/server/elastic/elastic.go — Elasticsearch integration
  • golang/nats-server/server/tpm/js_ek_tpm_windows.go — TPM key management (Windows)
  • golang/nats-server/server/tpm/js_ek_tpm_other.go — TPM key management (non-Windows)
  • golang/nats-server/internal/ — Internal utility packages (fastrand, ldap, ocsp, testhelper, antithesis)

Go Reference Files (Tests)

  • golang/nats-server/server/util_test.go
  • golang/nats-server/server/ring_test.go
  • golang/nats-server/server/rate_counter_test.go
  • golang/nats-server/server/ipqueue_test.go
  • golang/nats-server/server/errors_test.go

.NET Implementation Files (Source)

  • src/NATS.Server/IO/OutboundBufferPool.cs
  • src/NATS.Server/IO/AdaptiveReadBuffer.cs
  • src/NATS.Server/Server/AcceptLoopErrorHandler.cs

.NET Implementation Files (Tests)

  • tests/NATS.Server.Tests/IO/

Gap Inventory

golang/nats-server/server/util.go

Go Symbol Go File:Line Status .NET Equivalent Notes
refCountedUrlSet (type alias) golang/nats-server/server/util.go:34 NOT_APPLICABLE Internal clustering gossip helper; no equivalent needed in .NET port yet (clustering/gateway not fully ported)
refCountedUrlSet.addUrl golang/nats-server/server/util.go:203 NOT_APPLICABLE Part of gossip URL ref-counting; used only in route/gateway code not yet ported
refCountedUrlSet.removeUrl golang/nats-server/server/util.go:212 NOT_APPLICABLE Same as above
refCountedUrlSet.getAsStringSlice golang/nats-server/server/util.go:226 NOT_APPLICABLE Same as above
versionComponents (unexported) golang/nats-server/server/util.go:42 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:992 Inlined as VersionAtLeast helper in test file; production equivalent used in server
versionAtLeastCheckError (unexported) golang/nats-server/server/util.go:62 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:992 Logic folded into VersionAtLeast test helper
versionAtLeast (unexported) golang/nats-server/server/util.go:75 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:992 Ported as VersionAtLeast in InfrastructureGoParityTests; production uses System.Version comparisons
parseSize (unexported) golang/nats-server/server/util.go:82 PORTED src/NATS.Server/Protocol/NatsParser.cs:434 NatsParser.ParseSize(Span<byte>) — exact behavioral match including -1 on error; tested in InfrastructureGoParityTests
parseInt64 (unexported) golang/nats-server/server/util.go:113 PORTED src/NATS.Server/Protocol/NatsParser.cs:434 Folded into ParseSize / inline parser logic; behavior covered by parser tests
secondsToDuration (unexported) golang/nats-server/server/util.go:127 NOT_APPLICABLE Go-specific time.Duration helper; .NET uses TimeSpan.FromSeconds(double) directly
parseHostPort (unexported) golang/nats-server/server/util.go:134 PORTED src/NATS.Server/Server/ServerUtilities.cs:19 Added ParseHostPort(string, int) with default-port fallback and 0/-1 port normalization
urlsAreEqual (unexported) golang/nats-server/server/util.go:158 NOT_APPLICABLE Uses reflect.DeepEqual on *url.URL; not needed in .NET port (no equivalent URL gossip pattern yet)
comma (unexported) golang/nats-server/server/util.go:169 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:960 Ported as CommaFormat helper in InfrastructureGoParityTests (test-side only); monitoring output uses string.Format("{0:N0}") in production
natsListenConfig golang/nats-server/server/util.go:246 PORTED src/NATS.Server/NatsServer.cs .NET TcpListener / Socket used without OS TCP keepalives; keepalive is disabled by default in .NET socket setup matching Go behavior
natsListen (unexported) golang/nats-server/server/util.go:252 PORTED src/NATS.Server/NatsServer.cs Equivalent accept loop uses TcpListener.AcceptTcpClientAsync without system keepalives
natsDialTimeout (unexported) golang/nats-server/server/util.go:258 PORTED src/NATS.Server/Routes/RouteManager.cs:547 Added CreateRouteDialSocket() to explicitly disable TCP keepalive on outbound route dials before connect
redactURLList (unexported) golang/nats-server/server/util.go:270 PORTED src/NATS.Server/Server/ServerUtilities.cs:79 Added production RedactUrlList(IEnumerable<string>) that redacts per-URL user-info passwords
redactURLString (unexported) golang/nats-server/server/util.go:296 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:979 RedactUrl in InfrastructureGoParityTests matches behavior; also used in log redaction
getURLsAsString (unexported) golang/nats-server/server/util.go:308 NOT_APPLICABLE Internal URL slice utility for clustering; not needed in current .NET scope
copyBytes (unexported) golang/nats-server/server/util.go:317 PORTED (inline) .NET uses ReadOnlySpan<byte>.ToArray(), Array.Copy, or Buffer.BlockCopy equivalently throughout the codebase
copyStrings (unexported) golang/nats-server/server/util.go:328 NOT_APPLICABLE Go slice copying idiom; .NET uses LINQ .ToArray() or list copy directly
generateInfoJSON (unexported) golang/nats-server/server/util.go:339 PORTED src/NATS.Server/Protocol/NatsProtocol.cs NatsProtocol.WriteInfo() writes the INFO …\r\n frame directly to the write buffer
parallelTaskQueue (unexported) golang/nats-server/server/util.go:350 NOT_APPLICABLE Go goroutine pool pattern; .NET uses Parallel.ForEach, Task.WhenAll, or Channel<T> for equivalent parallelism

golang/nats-server/server/ring.go

Go Symbol Go File:Line Status .NET Equivalent Notes
closedClient (type) golang/nats-server/server/ring.go:17 PORTED src/NATS.Server/Monitoring/ClosedClient.cs ClosedClient C# record mirrors the Go struct; includes connection info, subscription details
closedRingBuffer (type) golang/nats-server/server/ring.go:25 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs ClosedConnectionRingBuffer — full ring buffer with capacity, count, totalClosed, thread-safe via Lock
newClosedRingBuffer golang/nats-server/server/ring.go:31 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:16 Constructor with capacity parameter
closedRingBuffer.append golang/nats-server/server/ring.go:39 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:37 Add(ClosedClient) — overwrites oldest on overflow
closedRingBuffer.next (unexported) golang/nats-server/server/ring.go:44 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs Inlined into Add_head = (_head + 1) % _buffer.Length
closedRingBuffer.len (unexported) golang/nats-server/server/ring.go:48 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:24 Count property
closedRingBuffer.totalConns (unexported) golang/nats-server/server/ring.go:55 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:29 TotalClosed property
closedRingBuffer.closedClients (unexported) golang/nats-server/server/ring.go:65 PORTED src/NATS.Server/Monitoring/ClosedConnectionRingBuffer.cs:52 GetAll() and GetRecent(int) — returns sorted copy; .NET returns newest-first (monitoring convention)

golang/nats-server/server/rate_counter.go

Go Symbol Go File:Line Status .NET Equivalent Notes
rateCounter (type) golang/nats-server/server/rate_counter.go:21 PORTED src/NATS.Server/Tls/TlsRateLimiter.cs TlsRateLimiter provides equivalent token-bucket rate limiting for TLS handshakes; also ApiRateLimiter for JetStream API
newRateCounter golang/nats-server/server/rate_counter.go:30 PORTED src/NATS.Server/Tls/TlsRateLimiter.cs:9 TlsRateLimiter(long tokensPerSecond) constructor
rateCounter.allow (unexported) golang/nats-server/server/rate_counter.go:37 PORTED src/NATS.Server/Server/RateCounter.cs:21 Added non-blocking Allow() with 1-second window and blocked-counter increment semantics
rateCounter.countBlocked (unexported) golang/nats-server/server/rate_counter.go:58 PORTED src/NATS.Server/Server/RateCounter.cs:42 Added CountBlocked() that returns and resets blocked count

golang/nats-server/server/sendq.go

Go Symbol Go File:Line Status .NET Equivalent Notes
outMsg (type) golang/nats-server/server/sendq.go:21 NOT_APPLICABLE Internal message envelope for Go goroutine-to-goroutine delivery; .NET internal system events use Channel<T> with typed event objects directly
sendq (type) golang/nats-server/server/sendq.go:28 NOT_APPLICABLE Go-specific goroutine-based internal send queue for system account messages; .NET equivalent is Channel<T> or InternalEventSystem dispatch
Server.newSendQ golang/nats-server/server/sendq.go:35 NOT_APPLICABLE Factory for goroutine-based queue; not applicable to .NET async model
sendq.internalLoop (unexported) golang/nats-server/server/sendq.go:41 NOT_APPLICABLE Go goroutine event loop; .NET uses await foreach on Channel<T> reader
outMsgPool golang/nats-server/server/sendq.go:103 NOT_APPLICABLE sync.Pool for outMsg structs; .NET uses ArrayPool<byte> or object pools via System.Buffers
sendq.send golang/nats-server/server/sendq.go:109 NOT_APPLICABLE Public entry point for internal system message dispatch; .NET internal event dispatch uses InternalEventSystem.PublishAsync

golang/nats-server/server/ipqueue.go

Go Symbol Go File:Line Status .NET Equivalent Notes
ipQueue[T] (generic type) golang/nats-server/server/ipqueue.go:25 NOT_APPLICABLE Go generics-based intra-process queue using goroutine channels; .NET uses System.Threading.Channels.Channel<T> which provides the same producer-consumer semantics natively
ipQueueOpts[T] golang/nats-server/server/ipqueue.go:38 NOT_APPLICABLE Options struct for ipQueue; .NET Channel.CreateBounded/CreateUnbounded options cover equivalent functionality
ipQueueOpt[T] (function type) golang/nats-server/server/ipqueue.go:45 NOT_APPLICABLE Functional options pattern; .NET uses BoundedChannelOptions
ipqMaxRecycleSize[T] golang/nats-server/server/ipqueue.go:49 NOT_APPLICABLE Pool recycling threshold; not needed with .NET GC
ipqSizeCalculation[T] golang/nats-server/server/ipqueue.go:57 NOT_APPLICABLE Size tracking callback; .NET channels track count natively
ipqLimitBySize[T] golang/nats-server/server/ipqueue.go:68 NOT_APPLICABLE Capacity limiting by byte size; .NET BoundedChannelOptions.Capacity limits by count; byte-size limiting is MISSING but not critical for current port scope
ipqLimitByLen[T] golang/nats-server/server/ipqueue.go:77 NOT_APPLICABLE Capacity limiting by count; maps to BoundedChannelOptions.Capacity
errIPQLenLimitReached golang/nats-server/server/ipqueue.go:83 NOT_APPLICABLE Error sentinel for capacity; .NET channels return false from TryWrite when full
errIPQSizeLimitReached golang/nats-server/server/ipqueue.go:84 NOT_APPLICABLE Same as above for size-based limit
newIPQueue[T] golang/nats-server/server/ipqueue.go:86 NOT_APPLICABLE Factory; equivalent is Channel.CreateBounded<T> or Channel.CreateUnbounded<T>
ipQueue[T].push golang/nats-server/server/ipqueue.go:113 NOT_APPLICABLE Maps to ChannelWriter<T>.TryWrite
ipQueue[T].pop golang/nats-server/server/ipqueue.go:152 NOT_APPLICABLE Maps to ChannelReader<T>.ReadAllAsync
ipQueue[T].popOne golang/nats-server/server/ipqueue.go:178 NOT_APPLICABLE Maps to ChannelReader<T>.TryRead
ipQueue[T].recycle golang/nats-server/server/ipqueue.go:215 NOT_APPLICABLE Slice pool return; not needed with .NET GC
ipQueue[T].len golang/nats-server/server/ipqueue.go:234 NOT_APPLICABLE Maps to ChannelReader<T>.Count
ipQueue[T].size golang/nats-server/server/ipqueue.go:242 NOT_APPLICABLE Byte-size tracking; no direct .NET equivalent but not needed
ipQueue[T].drain golang/nats-server/server/ipqueue.go:253 NOT_APPLICABLE Flush/clear; .NET channels are drained by completing the writer and reading remaining items
ipQueue[T].inProgress golang/nats-server/server/ipqueue.go:275 NOT_APPLICABLE In-flight count tracking; not needed in .NET model
ipQueue[T].unregister golang/nats-server/server/ipqueue.go:281 NOT_APPLICABLE Remove from server map; .NET uses ConcurrentDictionary.TryRemove

golang/nats-server/server/errors.go

Go Symbol Go File:Line Status .NET Equivalent Notes
ErrConnectionClosed golang/nats-server/server/errors.go:23 PORTED src/NATS.Server/Protocol/NatsProtocol.cs Protocol-level error strings defined as constants in NatsProtocol; connection close reason tracked via ClientClosedReason enum
ErrAuthentication golang/nats-server/server/errors.go:26 PORTED src/NATS.Server/Protocol/NatsProtocol.cs:30 ErrAuthorizationViolation constant
ErrAuthTimeout golang/nats-server/server/errors.go:29 PORTED src/NATS.Server/NatsClient.cs Auth timeout enforced; close reason AuthTimeout in ClientClosedReason
ErrAuthExpired golang/nats-server/server/errors.go:32 PORTED src/NATS.Server/NatsClient.cs Auth expiry enforced via connection deadline
ErrAuthProxyNotTrusted golang/nats-server/server/errors.go:35 PORTED src/NATS.Server/Auth/ Proxy trust handled in auth layer
ErrAuthProxyRequired golang/nats-server/server/errors.go:39 PORTED src/NATS.Server/Auth/ Proxy requirement enforced
ErrMaxPayload golang/nats-server/server/errors.go:43 PORTED src/NATS.Server/Protocol/NatsProtocol.cs:27 ErrMaxPayloadViolation constant
ErrMaxControlLine golang/nats-server/server/errors.go:46 PORTED src/NATS.Server/Protocol/NatsParser.cs Parser throws when control line exceeds MaxControlLineSize
ErrReservedPublishSubject golang/nats-server/server/errors.go:49 PORTED src/NATS.Server/NatsClient.cs Reserved subject check on publish
ErrBadPublishSubject golang/nats-server/server/errors.go:52 PORTED src/NATS.Server/Protocol/NatsProtocol.cs:28 ErrInvalidPublishSubject constant
ErrBadSubject golang/nats-server/server/errors.go:55 PORTED src/NATS.Server/Protocol/NatsProtocol.cs:29 ErrInvalidSubject constant
ErrBadQualifier golang/nats-server/server/errors.go:58 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:10 Added parity literal constant for bad transform qualifier error
ErrBadClientProtocol golang/nats-server/server/errors.go:61 PORTED src/NATS.Server/NatsClient.cs Protocol version validation on CONNECT
ErrTooManyConnections golang/nats-server/server/errors.go:64 PORTED src/NATS.Server/Protocol/NatsProtocol.cs:25 ErrMaxConnectionsExceeded constant
ErrTooManyAccountConnections golang/nats-server/server/errors.go:68 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:11 Added parity error literal constant; enforcement work remains tracked separately in account-limit behavior gaps
ErrLeafNodeLoop golang/nats-server/server/errors.go:72 PORTED src/NATS.Server/LeafNode/ Leaf node loop detection implemented
ErrTooManySubs golang/nats-server/server/errors.go:76 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:12 Added parity error literal constant
ErrTooManySubTokens golang/nats-server/server/errors.go:79 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:13 Added parity error literal constant
ErrClientConnectedToRoutePort golang/nats-server/server/errors.go:83 PORTED src/NATS.Server/Routes/ Wrong port detection on route listener
ErrClientConnectedToLeafNodePort golang/nats-server/server/errors.go:87 PORTED src/NATS.Server/LeafNode/ Wrong port detection on leaf node listener
ErrLeafNodeHasSameClusterName golang/nats-server/server/errors.go:91 PORTED src/NATS.Server/LeafNode/ Same-cluster-name rejection
ErrLeafNodeDisabled golang/nats-server/server/errors.go:94 PORTED src/NATS.Server/LeafNode/ Leaf node disabled check
ErrConnectedToWrongPort golang/nats-server/server/errors.go:98 PORTED src/NATS.Server/NatsServer.cs Port sniffing / wrong-port close
ErrAccountExists golang/nats-server/server/errors.go:102 PORTED src/NATS.Server/Auth/Account.cs Duplicate account registration check
ErrBadAccount golang/nats-server/server/errors.go:105 PORTED src/NATS.Server/Auth/ Bad/malformed account
ErrReservedAccount golang/nats-server/server/errors.go:108 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:14 Added parity error literal constant
ErrMissingAccount golang/nats-server/server/errors.go:111 PORTED src/NATS.Server/Auth/ Missing account lookup
ErrMissingService golang/nats-server/server/errors.go:114 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:15 Added parity error literal constant
ErrBadServiceType golang/nats-server/server/errors.go:117 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:16 Added parity error literal constant
ErrBadSampling golang/nats-server/server/errors.go:120 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:17 Added parity error literal constant
ErrAccountValidation golang/nats-server/server/errors.go:123 PORTED src/NATS.Server/Auth/ Account validation logic
ErrAccountExpired golang/nats-server/server/errors.go:126 PORTED src/NATS.Server/Auth/ Account expiry check
ErrNoAccountResolver golang/nats-server/server/errors.go:129 PORTED src/NATS.Server/Auth/ No resolver configured check
ErrAccountResolverUpdateTooSoon golang/nats-server/server/errors.go:132 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:18 Added parity error literal constant
ErrAccountResolverSameClaims golang/nats-server/server/errors.go:135 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:19 Added parity error literal constant
ErrStreamImportAuthorization golang/nats-server/server/errors.go:138 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:20 Added parity error literal constant
ErrStreamImportBadPrefix golang/nats-server/server/errors.go:141 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:21 Added parity error literal constant
ErrStreamImportDuplicate golang/nats-server/server/errors.go:144 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:22 Added parity error literal constant
ErrServiceImportAuthorization golang/nats-server/server/errors.go:147 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:23 Added parity error literal constant
ErrImportFormsCycle golang/nats-server/server/errors.go:150 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:24 Added parity error literal constant
ErrCycleSearchDepth golang/nats-server/server/errors.go:153 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:25 Added parity error literal constant
ErrClientOrRouteConnectedToGatewayPort golang/nats-server/server/errors.go:157 PORTED src/NATS.Server/Gateways/ Wrong port detection on gateway listener
ErrWrongGateway golang/nats-server/server/errors.go:161 PORTED src/NATS.Server/Gateways/ Wrong gateway name on connect
ErrGatewayNameHasSpaces golang/nats-server/server/errors.go:165 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs Config validation rejects spaces in gateway name
ErrNoSysAccount golang/nats-server/server/errors.go:169 PORTED src/NATS.Server/NatsServer.cs System account presence check
ErrRevocation golang/nats-server/server/errors.go:172 PORTED src/NATS.Server/Auth/ Credential revocation check
ErrServerNotRunning golang/nats-server/server/errors.go:175 PORTED src/NATS.Server/NatsServer.cs Server running state check
ErrServerNameHasSpaces golang/nats-server/server/errors.go:178 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:1434 Config validation; ConfigProcessorException thrown
ErrBadMsgHeader golang/nats-server/server/errors.go:181 PORTED src/NATS.Server/Protocol/NatsParser.cs Header parsing validation
ErrMsgHeadersNotSupported golang/nats-server/server/errors.go:185 PORTED src/NATS.Server/NatsClient.cs Headers-not-supported check
ErrNoRespondersRequiresHeaders golang/nats-server/server/errors.go:189 PORTED src/NATS.Server/NatsClient.cs No-responders validation
ErrClusterNameConfigConflict golang/nats-server/server/errors.go:193 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs Cluster/gateway name conflict validation
ErrClusterNameRemoteConflict golang/nats-server/server/errors.go:196 PORTED src/NATS.Server/Routes/ Remote cluster name mismatch
ErrClusterNameHasSpaces golang/nats-server/server/errors.go:199 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs Config validation
ErrMalformedSubject golang/nats-server/server/errors.go:202 PORTED src/NATS.Server/Subscriptions/SubjectMatch.cs Subject validation rejects malformed subjects
ErrSubscribePermissionViolation golang/nats-server/server/errors.go:205 PORTED src/NATS.Server/NatsClient.cs Subscribe permission check
ErrNoTransforms golang/nats-server/server/errors.go:208 PORTED src/NATS.Server/Server/ServerErrorConstants.cs:26 Added parity error literal constant
ErrCertNotPinned golang/nats-server/server/errors.go:211 PORTED src/NATS.Server/Tls/TlsHelper.cs Pinned cert validation
ErrDuplicateServerName golang/nats-server/server/errors.go:215 PORTED src/NATS.Server/Routes/ Duplicate server name on cluster connect
ErrMinimumVersionRequired golang/nats-server/server/errors.go:218 PORTED src/NATS.Server/Routes/ Minimum version enforcement on cluster
ErrInvalidMappingDestination golang/nats-server/server/errors.go:221 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Transform destination validation
ErrInvalidMappingDestinationSubject golang/nats-server/server/errors.go:223 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Invalid destination subject
ErrMappingDestinationNotUsingAllWildcards golang/nats-server/server/errors.go:226 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Wildcard coverage check
ErrUnknownMappingDestinationFunction golang/nats-server/server/errors.go:229 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Unknown function error
ErrMappingDestinationIndexOutOfRange golang/nats-server/server/errors.go:232 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Index out of range
ErrMappingDestinationNotEnoughArgs golang/nats-server/server/errors.go:235 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Not enough args error
ErrMappingDestinationInvalidArg golang/nats-server/server/errors.go:238 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Invalid arg error
ErrMappingDestinationTooManyArgs golang/nats-server/server/errors.go:241 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Too many args error
ErrMappingDestinationNotSupportedForImport golang/nats-server/server/errors.go:244 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Import-only wildcard restriction
mappingDestinationErr (type) golang/nats-server/server/errors.go:248 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Equivalent validation exceptions in transform code
mappingDestinationErr.Error golang/nats-server/server/errors.go:253 PORTED src/NATS.Server/Subscriptions/SubjectTransform.cs Exception message formatting
mappingDestinationErr.Is golang/nats-server/server/errors.go:257 NOT_APPLICABLE Go errors.Is interface; .NET uses is and catch (SpecificException) instead
configErr (type) golang/nats-server/server/errors.go:261 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:1434 ConfigProcessorException with error list
configErr.Source golang/nats-server/server/errors.go:267 PARTIAL src/NATS.Server/Configuration/ConfigProcessor.cs Source file/line tracking in errors is partial; exception message includes context but not file:line:col
configErr.Error golang/nats-server/server/errors.go:272 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs Exception Message property
unknownConfigFieldErr (type) golang/nats-server/server/errors.go:280 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:1597 Added UnknownConfigFieldWarning type with field/source metadata and Go-style warning message (unknown field <name>).
configWarningErr (type) golang/nats-server/server/errors.go:292 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:1588 Added ConfigWarningException base warning type to distinguish warning payloads from hard errors.
processConfigErr (type) golang/nats-server/server/errors.go:303 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:1434 ConfigProcessorException accumulates all errors
processConfigErr.Error golang/nats-server/server/errors.go:310 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs Message + Errors list
processConfigErr.Warnings golang/nats-server/server/errors.go:322 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:1581 Added ConfigProcessorException.Warnings list and wired unknown top-level field warnings into thrown config errors when validation errors are present.
processConfigErr.Errors golang/nats-server/server/errors.go:327 PORTED src/NATS.Server/Configuration/ConfigProcessor.cs:1437 ConfigProcessorException.Errors property
errCtx (type) golang/nats-server/server/errors.go:332 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1069 WrappedNatsException (test-file-scoped) mirrors the error context wrapping; production code uses standard .NET exception chaining
NewErrorCtx golang/nats-server/server/errors.go:338 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1069 Equivalent via new WrappedNatsException(inner, ctx) in tests; production uses new Exception(msg, inner)
errCtx.Unwrap golang/nats-server/server/errors.go:343 NOT_APPLICABLE Go errors.Unwrap interface; .NET uses Exception.InnerException
errCtx.Context golang/nats-server/server/errors.go:350 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1069 WrappedNatsException.FullTrace() extracts and returns context
UnpackIfErrorCtx golang/nats-server/server/errors.go:358 PORTED tests/NATS.Server.Tests/InfrastructureGoParityTests.cs:1075 WrappedNatsException.FullTrace() — recursive trace assembly matches Go's UnpackIfErrorCtx logic
errorsUnwrap (unexported) golang/nats-server/server/errors.go:371 NOT_APPLICABLE Go 1.13 compatibility shim; .NET uses Exception.InnerException directly
ErrorIs golang/nats-server/server/errors.go:382 NOT_APPLICABLE Go 1.13 compatibility shim for errors.Is; .NET uses is, catch, or Exception.GetType()

golang/nats-server/server/errors_gen.go

Go Symbol Go File:Line Status .NET Equivalent Notes
(entire file — code generator) golang/nats-server/server/errors_gen.go:1 NOT_APPLICABLE This is a //go:build ignore code generator that produces jetstream_errors_generated.go. The generated JetStream API error codes are ported directly as JetStreamApiError and integer error code constants in src/NATS.Server/JetStream/Api/. No need to port the generator itself.

golang/nats-server/server/sdm.go

Go Symbol Go File:Line Status .NET Equivalent Notes
SDMMeta (type) golang/nats-server/server/sdm.go:22 MISSING Subject Delete Marker metadata tracker; used inside stream.go for SDM/KV purge tracking. MsgScheduling not yet ported so SDMMeta is also absent.
SDMBySeq (type) golang/nats-server/server/sdm.go:27 MISSING Per-sequence SDM state (last flag + timestamp); needed by SDMMeta
newSDMMeta golang/nats-server/server/sdm.go:33 MISSING Constructor for SDMMeta
isSubjectDeleteMarker (unexported) golang/nats-server/server/sdm.go:42 MISSING Header inspection to detect SDM or KV purge markers; needed for FileStore tombstone handling
SDMMeta.empty golang/nats-server/server/sdm.go:47 MISSING Clear all tracking state
SDMMeta.trackPending golang/nats-server/server/sdm.go:56 MISSING Cache a pending SDM sequence
SDMMeta.removeSeqAndSubject golang/nats-server/server/sdm.go:66 MISSING Remove a confirmed SDM from tracking

golang/nats-server/server/scheduler.go

Go Symbol Go File:Line Status .NET Equivalent Notes
ErrMsgScheduleInvalidVersion golang/nats-server/server/scheduler.go:29 MISSING Error for unknown schedule snapshot version; needed when decoding binary schedule state
MsgScheduling (type) golang/nats-server/server/scheduler.go:35 MISSING Core message scheduler type — manages per-subject schedules, timer, THW integration; tests in FileStoreTombstoneTests.cs note this is not yet ported
MsgSchedule (type) golang/nats-server/server/scheduler.go:46 MISSING Per-subject schedule entry (seq + timestamp)
newMsgScheduling golang/nats-server/server/scheduler.go:51 MISSING Constructor with run callback
MsgScheduling.add golang/nats-server/server/scheduler.go:61 MISSING Add/replace a schedule entry
MsgScheduling.init (unexported) golang/nats-server/server/scheduler.go:66 MISSING Internal init with THW integration
MsgScheduling.update golang/nats-server/server/scheduler.go:81 MISSING Update timestamp of existing schedule
MsgScheduling.markInflight golang/nats-server/server/scheduler.go:93 MISSING Mark subject as currently being delivered
MsgScheduling.isInflight golang/nats-server/server/scheduler.go:99 MISSING Check if subject is in-flight
MsgScheduling.remove golang/nats-server/server/scheduler.go:104 MISSING Remove by sequence number
MsgScheduling.removeSubject golang/nats-server/server/scheduler.go:111 MISSING Remove by subject
MsgScheduling.clearInflight golang/nats-server/server/scheduler.go:119 MISSING Reset all in-flight tracking
MsgScheduling.resetTimer (unexported) golang/nats-server/server/scheduler.go:123 MISSING Recalculate next fire time from THW
MsgScheduling.getScheduledMessages (unexported) golang/nats-server/server/scheduler.go:158 MISSING Evaluate expired schedules; complex — includes pattern parsing, header manipulation
MsgScheduling.encode golang/nats-server/server/scheduler.go:249 MISSING Binary snapshot serialization
MsgScheduling.decode golang/nats-server/server/scheduler.go:267 MISSING Binary snapshot deserialization
parseMsgSchedule (unexported) golang/nats-server/server/scheduler.go:302 MISSING Parse @at ... / @every ... schedule patterns

golang/nats-server/server/ats/ats.go

Go Symbol Go File:Line Status .NET Equivalent Notes
TickInterval (const) golang/nats-server/server/ats/ats.go:25 MISSING 100ms tick interval constant for access-time service
Register golang/nats-server/server/ats/ats.go:42 MISSING Start the access-time goroutine (ref-counted). Used by FileStore on creation to get efficient nanosecond timestamps without calling time.Now() on every access.
Unregister golang/nats-server/server/ats/ats.go:64 MISSING Stop the access-time goroutine when last user unregisters
AccessTime golang/nats-server/server/ats/ats.go:76 MISSING Return cached Unix nanosecond timestamp (atomic load). .NET equivalent could use Interlocked-cached DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() but no such service exists yet

golang/nats-server/server/elastic/elastic.go

Go Symbol Go File:Line Status .NET Equivalent Notes
Pointer[T] (generic type) golang/nats-server/server/elastic/elastic.go:26 MISSING Elastic (weak/strong) reference wrapper using Go 1.24 weak.Pointer. Used for FileStore block caching to allow GC to reclaim blocks while keeping a strong ref when needed. No .NET equivalent ported.
Make[T] golang/nats-server/server/elastic/elastic.go:20 MISSING Factory for Pointer[T] from a strong pointer
Pointer[T].Set golang/nats-server/server/elastic/elastic.go:31 MISSING Update the weak/strong pointer
Pointer[T].Strengthen golang/nats-server/server/elastic/elastic.go:38 MISSING Promote weak ref to strong
Pointer[T].Weaken golang/nats-server/server/elastic/elastic.go:45 MISSING Demote strong ref to weak (allow GC)
Pointer[T].Value golang/nats-server/server/elastic/elastic.go:52 MISSING Get current value (strong if available, else weak)

golang/nats-server/server/tpm/js_ek_tpm_windows.go and js_ek_tpm_other.go

Go Symbol Go File:Line Status .NET Equivalent Notes
JsKeyTPMVersion golang/nats-server/server/tpm/js_ek_tpm_windows.go:34 DEFERRED TPM version constant; entire TPM subsystem deferred
regenerateSRK (unexported) golang/nats-server/server/tpm/js_ek_tpm_windows.go:51 DEFERRED Windows-only TPM2 SRK creation
natsTPMPersistedKeys (type) golang/nats-server/server/tpm/js_ek_tpm_windows.go:77 DEFERRED JSON-serializable key blob struct
writeTPMKeysToFile (unexported) golang/nats-server/server/tpm/js_ek_tpm_windows.go:85 DEFERRED Persist TPM key blobs to disk
readTPMKeysFromFile (unexported) golang/nats-server/server/tpm/js_ek_tpm_windows.go:115 DEFERRED Read TPM key blobs from disk
createAndSealJsEncryptionKey (unexported) golang/nats-server/server/tpm/js_ek_tpm_windows.go:146 DEFERRED Create NKey-based JetStream encryption key and seal to TPM
unsealJsEncrpytionKey (unexported) golang/nats-server/server/tpm/js_ek_tpm_windows.go:178 DEFERRED Unseal JetStream key from TPM
policyPCRPasswordSession (unexported) golang/nats-server/server/tpm/js_ek_tpm_windows.go:203 DEFERRED TPM2 policy session with PCR + password
LoadJetStreamEncryptionKeyFromTPM golang/nats-server/server/tpm/js_ek_tpm_windows.go:245 DEFERRED Main entry point; Windows only. Non-Windows stub returns error. Deferred: requires Microsoft.TPM or Tss.Net NuGet and Windows-only API surface.
LoadJetStreamEncryptionKeyFromTPM (stub) golang/nats-server/server/tpm/js_ek_tpm_other.go:21 NOT_APPLICABLE Non-Windows stub; .NET would use PlatformNotSupportedException equivalently

golang/nats-server/internal/fastrand/fastrand.go

Go Symbol Go File:Line Status .NET Equivalent Notes
Uint32 golang/nats-server/internal/fastrand/fastrand.go:12 NOT_APPLICABLE Links to runtime.fastrand via go:linkname — a Go runtime internal. .NET uses Random.Shared.Next() or RandomNumberGenerator equivalently. No need to port this internal.
Uint32n golang/nats-server/internal/fastrand/fastrand.go:17 NOT_APPLICABLE Same as above; maps to Random.Shared.Next(0, n)
Uint64 golang/nats-server/internal/fastrand/fastrand.go:20 NOT_APPLICABLE Same as above; maps to Random.Shared.NextInt64()

golang/nats-server/internal/ldap/dn.go

Go Symbol Go File:Line Status .NET Equivalent Notes
AttributeTypeAndValue (type) golang/nats-server/internal/ldap/dn.go:30 PARTIAL src/NATS.Server/Auth/TlsMapAuthenticator.cs .NET X500DistinguishedName used directly; no standalone AttributeTypeAndValue type
RelativeDN (type) golang/nats-server/internal/ldap/dn.go:37 PARTIAL src/NATS.Server/Auth/TlsMapAuthenticator.cs X500DistinguishedName.EnumerateRelativeDistinguishedNames() provides equivalent; no custom RelativeDN type
DN (type) golang/nats-server/internal/ldap/dn.go:43 PARTIAL src/NATS.Server/Auth/TlsMapAuthenticator.cs X500DistinguishedName (.NET BCL) used instead; no custom DN type
FromCertSubject golang/nats-server/internal/ldap/dn.go:48 PARTIAL src/NATS.Server/Auth/TlsMapAuthenticator.cs:31 Certificate subject extracted via X509Certificate2.SubjectName; does not support multi-value RDNs or full RFC 4514 ordering
FromRawCertSubject golang/nats-server/internal/ldap/dn.go:80 MISSING Raw ASN.1 subject parsing preserving original order; not implemented
ParseDN golang/nats-server/internal/ldap/dn.go:126 MISSING RFC 4514 DN string parser; not implemented. .NET uses X500DistinguishedName which parses RFC 2253 format but lacks the Go implementation's special-case handling
DN.Equal golang/nats-server/internal/ldap/dn.go:220 MISSING RFC 4517 distinguishedNameMatch comparison
DN.RDNsMatch golang/nats-server/internal/ldap/dn.go:234 MISSING Order-independent RDN matching
DN.AncestorOf golang/nats-server/internal/ldap/dn.go:258 MISSING DN ancestry check
RelativeDN.Equal golang/nats-server/internal/ldap/dn.go:278 MISSING RFC 4517 RDN equivalence
RelativeDN.hasAllAttributes (unexported) golang/nats-server/internal/ldap/dn.go:285 MISSING Attribute superset check
AttributeTypeAndValue.Equal golang/nats-server/internal/ldap/dn.go:302 MISSING Case-insensitive type + value comparison

golang/nats-server/internal/antithesis/

Go Symbol Go File:Line Status .NET Equivalent Notes
AssertUnreachable (noop build) golang/nats-server/internal/antithesis/noop.go:24 NOT_APPLICABLE Chaos testing assertion (noop when Antithesis SDK not active); .NET has no Antithesis SDK. xUnit's Assert.Fail() covers the reachability assertion pattern in tests.
Assert (noop build) golang/nats-server/internal/antithesis/noop.go:27 NOT_APPLICABLE Same as above; .NET uses Shouldly condition.ShouldBeTrue() in tests
AssertUnreachable (SDK build) golang/nats-server/internal/antithesis/test_assert.go:49 NOT_APPLICABLE Antithesis SDK wrapper; no .NET Antithesis SDK exists
Assert (SDK build) golang/nats-server/internal/antithesis/test_assert.go:83 NOT_APPLICABLE Same as above

golang/nats-server/internal/testhelper/ (ocsp.go / logging.go)

Go Symbol Go File:Line Status .NET Equivalent Notes
NewOCSPResponder golang/nats-server/internal/testhelper/ocsp.go (ocsp.go):45 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs .NET OCSP test helper implemented inline in test files using ASP.NET Core minimal APIs
NewOCSPResponderCustomAddress golang/nats-server/internal/testhelper/ocsp.go:40 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs Equivalent test helper
NewOCSPResponderDesignatedCustomAddress golang/nats-server/internal/testhelper/ocsp.go:50 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs Designated responder variant
NewOCSPResponderPreferringHTTPMethod golang/nats-server/internal/testhelper/ocsp.go:55 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs HTTP method preference variant
NewOCSPResponderCustomTimeout golang/nats-server/internal/testhelper/ocsp.go:60 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs Custom TTL variant
NewOCSPResponderBase golang/nats-server/internal/testhelper/ocsp.go:65 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs Base factory; all OCSP responder variants collapse to this
GetOCSPStatus golang/nats-server/internal/testhelper/ocsp.go:230 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs OCSP status extraction from TLS connection state
SetOCSPStatus golang/nats-server/internal/testhelper/ocsp.go:251 PORTED tests/NATS.Server.Tests/OcspStaplingTests.cs HTTP POST to set cert status on mock OCSP responder

.NET-Only Implementations (No Direct Go Equivalent)

The following .NET types were added to support the porting but have no exact Go counterpart:

.NET Type File Notes
OutboundBufferPool src/NATS.Server/IO/OutboundBufferPool.cs Tiered byte-array pool (512/4096/65536) replacing Go's sync.Pool + []byte dynamic sizing
AdaptiveReadBuffer src/NATS.Server/IO/AdaptiveReadBuffer.cs Buffer sizing state machine; mirrors client.go readLoop buffer growth/shrink logic
AcceptLoopErrorHandler src/NATS.Server/Server/AcceptLoopErrorHandler.cs Callback-based accept error delegation (no Go equivalent; Go logs inline)
TlsRateLimiter src/NATS.Server/Tls/TlsRateLimiter.cs Async token-bucket rate limiter for TLS handshakes

Keeping This File Updated

After porting work is completed:

  1. Update status: Change MISSING → PORTED or PARTIAL → PORTED for each item completed
  2. Add .NET path: Fill in the ".NET Equivalent" column with the actual file:line
  3. Re-count LOC: Update the LOC numbers in stillmissing.md:
    # Re-count .NET source LOC for this module
    find src/NATS.Server/IO/ src/NATS.Server/Server/ -name '*.cs' -type f -exec cat {} + | wc -l
    # Re-count .NET test LOC for this module
    find tests/NATS.Server.Tests/IO/ -name '*.cs' -type f -exec cat {} + | wc -l
    
  4. Add a changelog entry below with date and summary of what was ported
  5. Update the parity DB if new test mappings were created:
    sqlite3 docs/test_parity.db "INSERT INTO test_mappings (go_test_id, dotnet_test_id, confidence, notes) VALUES (?, ?, 'manual', 'ported in YYYY-MM-DD session')"
    

Change Log

Date Change By
2026-02-26 Ported config warning parity slice: added ConfigWarningException, UnknownConfigFieldWarning, and ConfigProcessorException.Warnings; wired unknown top-level fields as warning entries and added focused configuration parity tests. codex
2026-02-25 File created with LLM analysis instructions auto
2026-02-25 Full gap inventory populated — all Go source files analyzed, 131 symbols classified auto
2026-02-25 Ported missing errors.go parity literals into ServerErrorConstants and added targeted parity tests for the newly added constants codex