{"record":{"id":"bf08289a752af8f8","repo":"nats-io/nats-server","slug":"processremoteunsub-s","errorCode":null,"errorMessage":"processRemoteUnsub %s","messagePattern":"processRemoteUnsub (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/route.go","lineNumber":1435,"sourceCode":"\t\treturn nil\n\t}\n\n\tvar accountName string\n\t// Assume the account will be in the protocol.\n\taccInProto := true\n\n\tc.mu.Lock()\n\toriginSupport := c.route.lnocu\n\tlnSupport := c.route.ln\n\tif c.route != nil && len(c.route.accName) > 0 {\n\t\taccountName, accInProto = string(c.route.accName), false\n\t}\n\tc.mu.Unlock()\n\n\thasOrigin := leafUnsub && originSupport\n\torigin, accNameFromProto, subject, _, err := c.parseUnsubProto(arg, accInProto, hasOrigin)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"processRemoteUnsub %s\", err.Error())\n\t}\n\tnoOrigin := lnSupport && bytesToString(origin) == leafNoOriginCluster\n\tif accInProto {\n\t\taccountName = accNameFromProto\n\t}\n\t// Lookup the account\n\tvar acc *Account\n\tif v, ok := srv.accounts.Load(accountName); ok {\n\t\tacc = v.(*Account)\n\t} else {\n\t\tc.Debugf(\"Unknown account %q for subject %q\", accountName, subject)\n\t\treturn nil\n\t}\n\n\tc.mu.Lock()\n\tif c.isClosed() {\n\t\tc.mu.Unlock()\n\t\treturn nil","sourceCodeStart":1417,"sourceCodeEnd":1453,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/route.go#L1417-L1453","documentation":"processRemoteUnsub handles UNSUB protocol lines arriving from route/leaf connections. It first delegates parsing to parseUnsubProto and wraps any parse failure with the 'processRemoteUnsub' prefix. So this error means the remote UNSUB line was structurally invalid or referenced something unparseable per the negotiated protocol.","triggerScenarios":"Receiving an UNSUB on a route or leaf connection whose args do not match the expected layout (wrong field count, bad origin/account sentinels, malformed subject), causing parseUnsubProto to fail.","commonSituations":"Mixing server versions where leaf-node origin sentinels differ, third-party leaf node implementations with protocol bugs, or garbled traffic over the remote link.","solutions":["Upgrade both sides of the route/leaf connection to matching NATS Server versions","Fix the peer implementation to emit spec-compliant UNSUB lines","Check negotiated features (origin support, account-in-proto) match what the peer sends","Capture the raw line with protocol tracing to pinpoint the malformed field"],"exampleFix":"// before (peer)\n\"UNSUB subj sid\\r\\n\" // subject where sid expected\n// after\n\"UNSUB <sid>\\r\\n\"","handlingStrategy":"try-catch","validationCode":"// Server operators: pin and match NATS Server versions on both ends\nif serverVersionA != serverVersionB {\n    return fmt.Errorf(\"version skew on route/leaf link: %s vs %s\", serverVersionA, serverVersionB)\n}","typeGuard":null,"tryCatchPattern":"// Go: wrap connection error handler to log and reconnect on parse failures\nfunc (h *handler) OnRemoteError(err error) {\n    if strings.Contains(err.Error(), \"processRemoteUnsub\") {\n        log.Errorf(\"remote unsub parse failure: %v; reconnecting peer\", err)\n        h.reconnectPeer()\n    }\n}","preventionTips":["Keep route/leaf peers on matching NATS Server versions","Verify leaf-node clients implement the negotiated origin/account sentinels","Enable protocol tracing when debugging remote link issues"],"tags":["nats-server","protocol","unsub","leaf-nodes"],"backgroundTag":"malformed-protocol-frame","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}