{"record":{"id":"b60c0b95628003e9","repo":"slackhq/nebula","slug":"errmissingcontent","errorCode":"ErrMissingContent","errorMessage":"expected handshake content but message was empty","messagePattern":"expected handshake content but message was empty","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"handshake/errors.go","lineNumber":14,"sourceCode":"package handshake\n\nimport \"errors\"\n\nvar (\n\tErrInitiateOnResponder     = errors.New(\"initiate called on responder\")\n\tErrInitiateAlreadyCalled   = errors.New(\"initiate already called\")\n\tErrInitiateNotCalled       = errors.New(\"initiate must be called before ProcessPacket for initiators\")\n\tErrPacketTooShort          = errors.New(\"packet too short\")\n\tErrPublicKeyMismatch       = errors.New(\"public key mismatch between certificate and handshake\")\n\tErrIncompleteHandshake     = errors.New(\"handshake completed without receiving required content\")\n\tErrMachineFailed           = errors.New(\"handshake machine has failed\")\n\tErrUnknownSubtype          = errors.New(\"unknown handshake subtype\")\n\tErrMissingContent          = errors.New(\"expected handshake content but message was empty\")\n\tErrUnexpectedContent       = errors.New(\"received unexpected handshake content\")\n\tErrInvalidRemoteIndex      = errors.New(\"peer sent an invalid index in handshake payload\")\n\tErrIndexAllocation         = errors.New(\"failed to allocate local index\")\n\tErrNoCredential            = errors.New(\"no handshake credential available for cert version\")\n\tErrAsymmetricCipherKeys    = errors.New(\"noise produced only one cipher key\")\n\tErrMultiMessageUnsupported = errors.New(\"multi-message handshake patterns are not yet supported by the manager\")\n\tErrSubtypeMismatch         = errors.New(\"packet subtype does not match handshake machine subtype\")\n)\n","sourceCodeStart":1,"sourceCodeEnd":23,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/handshake/errors.go#L1-L23","documentation":"ErrMissingContent is returned by processPayload when a decrypted handshake message was empty but the pattern flags for that message expect a payload and/or certificate. The peer sent nothing where the protocol required content, so the handshake cannot proceed and the machine is marked failed.","triggerScenarios":"processPayload receives nil/empty message bytes while msgFlags{expectsPayload: true, expectsCert: true} (handshake/machine.go:289); exercised in machine_test.go:188.","commonSituations":"Peer sends an empty final handshake frame after a failure on its side; a truncated transmission; peer version that does not attach cert/payload to the expected message.","solutions":["Have the peer attach its payload and certificate to the message the pattern expects","Retry the handshake from scratch in case of a transient truncation","Verify both peers run the same handshake pattern definition"],"exampleFix":"// before: peer writes final message without content\nbuf := m.hs.WriteMessage()\nconn.Write(buf)\n\n// after\nbuf := m.hs.WriteMessage(nil)\nbuf = handshake.AppendPayload(buf, payload)\nbuf = handshake.AppendCert(buf, cert)\nconn.Write(buf)","handlingStrategy":"try-catch","validationCode":"if len(msg) == 0 && patternExpectsContent(stage) {\n    return fmt.Errorf(\"peer sent empty handshake message at stage %d\", stage)\n}","typeGuard":"func msgHasRequiredContent(msg []byte, flags handshake.MsgFlags) bool {\n    return len(msg) > 0 || !(flags.ExpectsPayload || flags.ExpectsCert)\n}","tryCatchPattern":"res, err := m.ProcessPacket(out, pkt)\nif errors.Is(err, handshake.ErrMissingContent) {\n    // peer must re-send with payload/cert attached; restart handshake\n    return restartHandshake(conn)\n}","preventionTips":["Ensure peer attaches payload and cert to the exact messages the pattern expects","Use length-prefixed framing to prevent message truncation","Cross-version integration tests for handshake message layout"],"tags":["handshake","protocol","noise"],"backgroundTag":"handshake-missing-content","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}