slackhq/nebula · error

marshalling certificate details failed: %w

Error message

marshalling certificate details failed: %w

What it means

marshalForSigning serializes the certificate's details via details.Marshal() before signing; if that marshalling fails, this wrapped error is returned. Details marshalling can fail on invalid inner data (e.g. network entries or a non-hex issuer), so this error wraps the underlying cause.

Source

Thrown at cert/cert_v2.go:465

					return NewErrInvalidCertificateProperties("IPv4 unsafe networks require an IPv4 address assignment: %s", network)
				}
			}
		}
	}

	slices.SortFunc(c.details.unsafeNetworks, comparePrefix)
	err = findDuplicatePrefix(c.details.unsafeNetworks)
	if err != nil {
		return err
	}

	return nil
}

func (c *certificateV2) marshalForSigning() ([]byte, error) {
	d, err := c.details.Marshal()
	if err != nil {
		return nil, fmt.Errorf("marshalling certificate details failed: %w", err)
	}
	c.rawDetails = d

	b := make([]byte, len(c.rawDetails)+1+len(c.publicKey))
	copy(b, c.rawDetails)
	b[len(c.rawDetails)] = byte(c.curve)
	copy(b[len(c.rawDetails)+1:], c.publicKey)
	return b, nil
}

func (c *certificateV2) setSignature(b []byte) error {
	if len(b) == 0 {
		return ErrEmptySignature
	}
	c.signature = b
	return nil
}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Inspect the wrapped cause (%w) to find which details field failed.
  2. Validate that d.issuer is a valid hex string before signing.
  3. Ensure network entries (host, mask, etc.) are fully populated and valid before marshalling.

Example fix

// before
ca, _ := cert.NewCertificate(vpnNetworks, opts)
sign, err := ca.Marshal() // marshalling certificate details failed: failed to decode issuer: ...
// after
certDetails.Issuer = hex.EncodeToString(caCert.Raw()) // issuer must be hex
sign, err := ca.Marshal()
Defensive patterns

Strategy: try-catch

Validate before calling

if certDetails.Issuer != "" {
    if _, err := hex.DecodeString(certDetails.Issuer); err != nil {
        return fmt.Errorf("issuer must be hex: %w", err)
    }
}

Type guard

func isHex(s string) bool {
    _, err := hex.DecodeString(s)
    return err == nil
}

Try / catch

raw, err := c.Marshal() // triggers marshalForSigning
if err != nil && strings.Contains(err.Error(), "marshalling certificate details failed") {
    log.Fatalf("certificate details invalid: %v", err) // err wraps root cause
}

Prevention

When it happens

Trigger: Building/signing a certificate whose details contain data that fails Marshal: a network entry whose MarshalBinary errors, or an issuer string that is not valid hex, triggered via certificate creation/signing paths.

Common situations: Programmatically constructed certificates with malformed networks or issuer fields, fuzz/testing of the signing path, or corrupt in-memory certificate structs.

Understand the failure class

Related errors


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