slackhq/nebula · critical
ErrNoCredential
ErrNoCredential
Error message
%w: %v
What it means
ErrNoCredential is returned during outgoing handshake marshaling when the node is asked to include its certificate (flags.expectsCert) but no certificate credential is available for the local certificate version m.myVersion. getCred(myVersion) returned nil, meaning the local cert store has no usable certificate for that version.
Source
Thrown at handshake/machine.go:409
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrIndexAllocation, err)
}
m.result.LocalIndex = index
m.indexAllocated = true
}
if m.result.Initiator {
p.InitiatorIndex = m.result.LocalIndex
} else {
p.ResponderIndex = m.result.LocalIndex
p.InitiatorIndex = m.result.RemoteIndex
}
p.Time = uint64(time.Now().UnixNano())
}
if flags.expectsCert {
cred := m.getCred(m.myVersion)
if cred == nil {
return nil, fmt.Errorf("%w: %v", ErrNoCredential, m.myVersion)
}
p.Cert = cred.Bytes
p.CertVersion = uint32(cred.Cert.Version())
m.result.MyCert = cred.Cert
}
return MarshalPayload(nil, p), nil
}
func (m *Machine) buildResponse(out []byte) ([]byte, *noise.CipherState, *noise.CipherState, error) {
flags := m.myMsgFlags()
hsBytes, err := m.marshalOutgoing(flags)
if err != nil {
return nil, nil, nil, err
}
// Extend out by header.Len to make room for the header. slices.Grow is a
// no-op when the cap is already sufficient (the zero-copy case where theView on GitHub (pinned to dd8f660c0a)
Solutions
- Load a certificate matching the machine's myVersion before initiating handshakes (check cert build/version)
- Re-issue or convert the host certificate to the expected version format
- Verify config 'pki' paths point to a valid cert/key pair and that startup loading succeeded
- Upgrade/downgrade the nebula binary so myVersion matches the certificate version
Example fix
// before: machine built with myVersion = cert.Version2 but only a v1 cert loaded
// after: ensure the loaded credential version matches
cred := m.getCred(m.myVersion)
if cred == nil {
// re-load or re-sign the host cert for the required version
return nil, fmt.Errorf("no %v credential loaded; update pki cert", m.myVersion)
} Defensive patterns
Strategy: validation
Validate before calling
cred := m.getCred(m.myVersion)
if cred == nil {
return errors.New("no local certificate loaded for handshake version; fix pki config before initiating")
} Type guard
func hasCredential(m *Machine) bool {
return m.getCred(m.myVersion) != nil
} Prevention
- Verify cert loads at startup and log the loaded cert version
- Keep pki.cert/pki.key paths correct in config
- Align node binary version with certificate version before rolling upgrades
When it happens
Trigger: Calling handshake Initiate/buildResponse when expectsCert is set but the local host has no certificate loaded for the current myVersion (e.g. cert v1 vs v2 mismatch between loaded credentials and machine version).
Common situations: Starting nebula with a v2 certificate while the handshake machine is pinned to v1 (or vice versa); cert failed to load/parse at startup; cert was removed by a reload; mixing node versions in a rolling upgrade.
Related errors
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/fe1362ca5c3ae289.
Report an issue: GitHub.