{"record":{"id":"98dcfed90059d003","repo":"hashicorp/nomad","slug":"bitmap-must-be-byte-aligned","errorCode":null,"errorMessage":"bitmap must be byte aligned","messagePattern":"bitmap must be byte aligned","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/bitmap.go","lineNumber":20,"sourceCode":"// SPDX-License-Identifier: BUSL-1.1\n\npackage structs\n\nimport (\n\t\"fmt\"\n\t\"slices\"\n)\n\n// Bitmap is a simple uncompressed bitmap\ntype Bitmap []byte\n\n// NewBitmap returns a bitmap with up to size indexes\nfunc NewBitmap(size uint) (Bitmap, error) {\n\tif size == 0 {\n\t\treturn nil, fmt.Errorf(\"bitmap must be positive size\")\n\t}\n\tif size&7 != 0 {\n\t\treturn nil, fmt.Errorf(\"bitmap must be byte aligned\")\n\t}\n\tb := make([]byte, size>>3)\n\treturn Bitmap(b), nil\n}\n\n// Copy returns a copy of the Bitmap\nfunc (b Bitmap) Copy() (Bitmap, error) {\n\tif b == nil {\n\t\treturn nil, fmt.Errorf(\"can't copy nil Bitmap\")\n\t}\n\n\traw := make([]byte, len(b))\n\tcopy(raw, b)\n\treturn Bitmap(raw), nil\n}\n\n// Size returns the size of the bitmap\nfunc (b Bitmap) Size() uint {","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/bitmap.go#L2-L38","documentation":"NewBitmap only supports sizes that are multiples of 8 (byte aligned), since the Bitmap is stored as a raw []byte and a non-aligned bit count would overflow the last byte. Any size where size&7 != 0 is rejected with this error. This is an internal invariant of Nomad's port bitmap implementation.","triggerScenarios":"Calling structs.NewBitmap(size) where size is not a multiple of 8 - e.g. NewBitmap(10), or getDynamicPortsPrecise computing a range whose length isn't byte aligned.","commonSituations":"Custom resource math producing port counts like 1001; tests constructing oddly sized bitmaps; plugin code allocating bitmap capacity from arbitrary range lengths.","solutions":["Round the requested size up to the next multiple of 8 before calling NewBitmap (size = (size + 7) & ^uint(7)).","Compute port-range sizes as (to - from + 1) and align to 8.","If only the exact bit count matters, allocate the aligned size and ignore trailing bits."],"exampleFix":"// before\nbm, err := structs.NewBitmap(uint(len(ports))) // len=10 -> error\n// after\nsize := uint(len(ports))\nsize = (size + 7) & ^uint(7)\nbm, err := structs.NewBitmap(size)","handlingStrategy":"validation","validationCode":"size := uint(n)\nif size&7 != 0 {\n    size = (size + 7) & ^uint(7)\n}\nbm, err := structs.NewBitmap(size)","typeGuard":null,"tryCatchPattern":"bm, err := structs.NewBitmap(size)\nif err != nil && strings.Contains(err.Error(), \"byte aligned\") {\n    bm, err = structs.NewBitmap((size + 7) & ^uint(7))\n}","preventionTips":["Always round bitmap sizes up to a multiple of 8 before construction.","Centralize bitmap allocation in one helper that performs the alignment.","Add an assertion/log when an unaligned size is requested to catch upstream math bugs."],"tags":["nomad","bitmap","validation","alignment"],"backgroundTag":"invalid-input-value","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}