Errors¶
Every sentinel is declared with errors.NewSentinel and carries a namespaced kind, so its identity
survives crossing a process boundary and it captures no stack at package initialisation.
| Sentinel | Kind | Returned when |
|---|---|---|
ErrNetworkModeUnsupported |
nats.network_mode_unsupported |
An embedded server would listen or mesh |
ErrCredentialInURL |
nats.credential_in_url |
A URL carries user information |
ErrInsecureCredential |
nats.insecure_credential |
A credential would cross an unencrypted scheme |
ErrUnboundedSubscription |
nats.unbounded_subscription |
A pending limit is not positive |
ErrNotConnected |
nats.not_connected |
A client is not connected: not yet, reconnecting, or closed |
ErrNoStoreDir |
nats.no_store_dir |
JetStream is set with no StoreDir |
ErrNoClusterName |
nats.no_cluster_name |
Routes is set with no ClusterName |
ErrNoTarget |
nats.no_target |
A client has neither a URL nor an in-process server |
ErrAmbiguousTarget |
nats.ambiguous_target |
A client has both |
ErrNotReady |
nats.not_ready |
An embedded server did not accept connections in time |
ErrUnbounded |
nats.unbounded |
A stream or bucket would be created with no limit |
Why these are refusals rather than defaults¶
Each one is a case where a sensible-looking default would fail later, quietly, somewhere else.
A listening server would accept anything that could reach it: no TLS, no authentication, and a client's token neither required nor protected. Refusing means the unsafe surface does not exist.
A credential in a URL puts a secret in a struct that gets logged, dumped and committed.
A credential over nats:// is bearer material in plaintext. Anyone on the path has it.
A non-positive pending limit means unlimited to NATS, which is the unbounded queue the bound exists to prevent.
A JetStream server with no store directory writes where it pleases. That differs by host, so the first time it matters is a restart that lost data on one node and not the others.
A client with two targets has been told two different things. Picking one is how a service ends up talking to a broker nobody thought it was talking to.
ErrNotConnected is not always a failure¶
Start returns once the client is trying, not once it has connected — the initial connect uses
the same retry policy as every reconnect. So "not yet" is an ordinary state, and
WaitReady is how a caller waits for it to stop
being true.
It is also what a publish returns while the connection is down. A publish during a reconnect is
refused, not held: nats.go would otherwise accept it into an 8 MiB buffer and return nil for
a message that has not been sent, losing the lot if that buffer fills. A bound nobody set is a shed
nobody sees, and that applies on the write path too.
This sentinel therefore covers not-yet, reconnecting and closed. Readiness and Liveness
distinguish them: reconnecting is not ready
but is alive; closed is neither.
ErrUnbounded is what the module owns about JetStream¶
Client.Stream, Client.KeyValue and Client.ObjectStore refuse anything created with no
MaxAge, MaxMsgs, MaxBytes or TTL.
Every JetStream limit defaults to unlimited, and NATS' own documentation warns that this exhausts storage — so a stream created without one is bounded by the volume rather than by anything a person chose, and the failure arrives at whatever hour the volume fills.
A caller can still reach JetStream through Client.Raw() and create whatever it likes. The refusal
is a guardrail on the path this module offers, not a cage.