slackhq/nebula · error
ErrNoCredential
ErrNoCredential
Error message
no handshake credential available for cert version
What it means
ErrNoCredential is returned by NewMachine, validateCert, and marshalOutgoing when getCred(version) finds no handshake credential registered for the required certificate version. The node cannot sign or validate certificates for that version without the matching credential. It is wrapped with the requested version number for diagnostics.
Source
Thrown at handshake/errors.go:18
package handshake
import "errors"
var (
ErrInitiateOnResponder = errors.New("initiate called on responder")
ErrInitiateAlreadyCalled = errors.New("initiate already called")
ErrInitiateNotCalled = errors.New("initiate must be called before ProcessPacket for initiators")
ErrPacketTooShort = errors.New("packet too short")
ErrPublicKeyMismatch = errors.New("public key mismatch between certificate and handshake")
ErrIncompleteHandshake = errors.New("handshake completed without receiving required content")
ErrMachineFailed = errors.New("handshake machine has failed")
ErrUnknownSubtype = errors.New("unknown handshake subtype")
ErrMissingContent = errors.New("expected handshake content but message was empty")
ErrUnexpectedContent = errors.New("received unexpected handshake content")
ErrInvalidRemoteIndex = errors.New("peer sent an invalid index in handshake payload")
ErrIndexAllocation = errors.New("failed to allocate local index")
ErrNoCredential = errors.New("no handshake credential available for cert version")
ErrAsymmetricCipherKeys = errors.New("noise produced only one cipher key")
ErrMultiMessageUnsupported = errors.New("multi-message handshake patterns are not yet supported by the manager")
ErrSubtypeMismatch = errors.New("packet subtype does not match handshake machine subtype")
)
View on GitHub (pinned to dd8f660c0a)
Solutions
- Register/load a credential for the required cert version before starting handshakes (verify getCred returns non-nil)
- Check the credentials directory/key files are present and readable in the deployment
- Align cert versions between peers, or add support for the peer's version
- Gate handshake serving behind credential-load completion to avoid startup races
Example fix
// before
m, err := handshake.NewMachine(cs, 2, getCred) // getCcred(nil) for v2
// after
if getCred(2) == nil {
return fmt.Errorf("credentials for cert version 2 not loaded")
}
m, err := handshake.NewMachine(cs, 2, getCred) Defensive patterns
Strategy: validation
Validate before calling
if getCred(certVersion) == nil {
return fmt.Errorf("no handshake credential loaded for cert version %d", certVersion)
} Type guard
func credentialsReady(versions ...int) bool {
for _, v := range versions {
if getCred(v) == nil {
return false
}
}
return true
} Try / catch
m, err := handshake.NewMachine(cs, version, getCred)
if errors.Is(err, handshake.ErrNoCredential) {
log.Printf("credential for version %v missing; refusing handshake", version)
return
} Prevention
- Load and verify all credential versions at startup before serving handshakes
- Keep old-version credentials during rolling upgrades
- Health-check that getCred returns non-nil for every advertised version
When it happens
Trigger: NewMachine (machine.go:91) builds a machine for a version whose credential lookup returns nil; validateCert (machine.go:346) hits the same during a handshake when m.myVersion has no registered credential.
Common situations: Credential store not yet loaded at handshake time (startup race); peer requests a newer certificate version than this node has keys for; credentials directory misconfigured or empty after redeploy; version bump without distributing new keys.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/590e42867ea32832.
Report an issue: GitHub.