slackhq/nebula · error

ErrEmptyRawDetails

ErrEmptyRawDetails

Error message

empty rawDetails not allowed

What it means

ErrEmptyRawDetails is returned by certificateV2's Marshal and MarshalForHandshakes when rawDetails is nil. Marshalling serializes the stored raw details into the wire format; without them there is nothing to encode, so both methods fail fast.

Source

Thrown at cert/errors.go:39

	ErrPrivateKeyEncrypted        = errors.New("private key must be decrypted")
	ErrCaNotFound                 = errors.New("could not find ca for the certificate")
	ErrUnknownVersion             = errors.New("certificate version unrecognized")
	ErrCertPubkeyPresent          = errors.New("certificate has unexpected pubkey present")
	ErrCurveMismatch              = errors.New("certificate curve does not match CA")

	ErrInvalidPEMBlock                   = errors.New("input did not contain a valid PEM encoded block")
	ErrInvalidPEMCertificateBanner       = errors.New("bytes did not contain a proper certificate banner")
	ErrInvalidPEMX25519PublicKeyBanner   = errors.New("bytes did not contain a proper X25519 public key banner")
	ErrInvalidPEMX25519PrivateKeyBanner  = errors.New("bytes did not contain a proper X25519 private key banner")
	ErrInvalidPEMEd25519PublicKeyBanner  = errors.New("bytes did not contain a proper Ed25519 public key banner")
	ErrInvalidPEMEd25519PrivateKeyBanner = errors.New("bytes did not contain a proper Ed25519 private key banner")

	ErrNoPeerStaticKey = errors.New("no peer static key was present")
	ErrNoPayload       = errors.New("provided payload was empty")

	ErrMissingDetails  = errors.New("certificate did not contain details")
	ErrEmptySignature  = errors.New("empty signature")
	ErrEmptyRawDetails = errors.New("empty rawDetails not allowed")
)

type ErrInvalidCertificateProperties struct {
	str string
}

func NewErrInvalidCertificateProperties(format string, a ...any) error {
	return &ErrInvalidCertificateProperties{fmt.Sprintf(format, a...)}
}

func (e *ErrInvalidCertificateProperties) Error() string {
	return e.str
}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Populate rawDetails (e.g. via details.Marshal() or the normal construction path) before calling Marshal/MarshalForHandshakes
  2. Check that the certificate was built through the library constructor rather than as a bare struct literal
  3. Validate the source certificate bytes were parsed completely before marshalling

Example fix

// before
c := &certificateV2{}
b, err := c.Marshal() // rawDetails nil
// after
rd, err := c.details.Marshal()
c.rawDetails = rd
b, err := c.Marshal()
Defensive patterns

Strategy: validation

Validate before calling

if c.rawDetails == nil {
    return fmt.Errorf("certificate not initialized: rawDetails missing")
}

Type guard

func marshalable(c *cert.CertificateV2) bool {
    _, err := c.Marshal()
    return err == nil
}

Try / catch

b, err := c.MarshalForHandshakes()
if errors.Is(err, cert.ErrEmptyRawDetails) {
    // certificate was never populated; rebuild from source
}

Prevention

When it happens

Trigger: Calling MarshalForHandshakes() or Marshal() on a certificateV2 whose rawDetails is nil — e.g. a zero-value certificate, or one deserialized from input lacking the details section.

Common situations: Constructing a certificateV2 by hand in tests/tools without setting rawDetails; truncated or corrupt certificate bytes dropping the details field; calling Marshal before the certificate is fully initialized.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/5095a546d85df291. Report an issue: GitHub.