nats-io/nats-server · warning

unsupported BER encoding

Error message

unsupported BER encoding

What it means

memStore.Snapshot is a deliberately unimplemented method in the in-memory store; it always returns a 'no impl' error. The memStore is used for ephemeral/no-persistence streams, so full snapshotting is unsupported. Callers must use EncodedStreamState instead when working with a memStore-backed stream.

Source

Thrown at internal/ldap/dn.go:177

			dst := []byte{0}
			n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
			if err != nil {
				return nil, fmt.Errorf("failed to decode escaped character: %s", err)
			} else if n != 1 {
				return nil, fmt.Errorf("expected 1 byte when un-escaping, got %d", n)
			}
			buffer.WriteByte(dst[0])
			i++
		case char == '\\':
			unescapedTrailingSpaces = 0
			escaping = true
		case char == '=':
			attribute.Type = stringFromBuffer()
			// Special case: If the first character in the value is # the following data
			// is BER encoded. Throw an error since not supported right now.
			if len(str) > i+1 && str[i+1] == '#' {
				return nil, errors.New("unsupported BER encoding")
			}
		case char == ',' || char == '+':
			// We're done with this RDN or value, push it
			if len(attribute.Type) == 0 {
				return nil, errors.New("incomplete type, value pair")
			}
			attribute.Value = stringFromBuffer()
			rdn.Attributes = append(rdn.Attributes, attribute)
			attribute = new(AttributeTypeAndValue)
			if char == ',' {
				dn.RDNs = append(dn.RDNs, rdn)
				rdn = new(RelativeDN)
				rdn.Attributes = make([]*AttributeTypeAndValue, 0)
			}
		case char == ' ' && buffer.Len() == 0:
			// ignore unescaped leading spaces
			continue
		default:

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Do not call Snapshot on memory-backed streams; use EncodedStreamState or StreamState instead
  2. Check the store type (StorageMemory) before invoking Snapshot and skip/handle accordingly
  3. Use the generic snapshot path only for fileStore-backed streams

Example fix

// before
snap, err := store.Snapshot(10*time.Second, true, true)
// after
if _, isMem := store.(*memStore); isMem {
    return errors.New("snapshot not supported for memory streams")
}
snap, err := store.Snapshot(10*time.Second, true, true)
Defensive patterns

Strategy: fallback

Validate before calling

if _, isMem := store.(*memStore); isMem {
    // use EncodedStreamState / StreamState instead of Snapshot
}

Type guard

func supportsSnapshot(s interface{}) bool {
    _, isMem := s.(*memStore)
    return !isMem
}

Try / catch

snap, err := store.Snapshot(d, includeDeleted, checkMsgs)
if err != nil && strings.Contains(err.Error(), "no impl") {
    // fall back to memory-store state access
}

Prevention

When it happens

Trigger: Calling Snapshot(_, _, _, _) on a *memStore instance — e.g. generic store code that snapshots all stream types without checking the storage type.

Common situations: Monitoring or migration tooling calling the Store interface's Snapshot method on a stream configured with memory storage; interface-level code assuming all store implementations support snapshots.

Related errors


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