{"record":{"id":"e8274ba1e54d1158","repo":"hashicorp/nomad","slug":"can-t-copy-nil-bitmap","errorCode":null,"errorMessage":"can't copy nil Bitmap","messagePattern":"can't copy nil Bitmap","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/bitmap.go","lineNumber":29,"sourceCode":"// 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 {\n\treturn uint(len(b) << 3)\n}\n\n// Set is used to set the given index of the bitmap\nfunc (b Bitmap) Set(idx uint) {\n\tbucket := idx >> 3\n\tmask := byte(1 << (idx & 7))\n\tb[bucket] |= mask\n}","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/bitmap.go#L11-L47","documentation":"Bitmap.Copy refuses to copy a nil Bitmap: a nil receiver has no backing bytes and copying it is treated as a programming error rather than silently returning nil. The method checks b == nil and returns this error so callers distinguish 'no data' from 'copy of empty data'.","triggerScenarios":"Calling Copy() on a Bitmap variable that was never initialized (declared but not returned from NewBitmap), commonly via getDynamicPortsPrecise on a NetworkResource whose Ports bitmap field is nil.","commonSituations":"Deserialized NetworkResource structs missing the internal bitmap (e.g. built by older code paths or hand-constructed in tests); copying a Bitmap from a struct field that was never populated.","solutions":["Initialize the Bitmap with NewBitmap before copying.","Guard the call: if b == nil { return nil, nil } at the call site.","Ensure NetworkResource objects were built through Nomad's normal port-allocation paths, which populate the bitmap.","In tests, construct the bitmap explicitly instead of relying on zero values."],"exampleFix":"// before\nnet.Ports.Copy()\n// after\nif net.Ports == nil {\n    net.Ports, err = structs.NewBitmap(1024)\n    if err != nil { return err }\n}\ncopy, err := net.Ports.Copy()","handlingStrategy":"type-guard","validationCode":"if b == nil {\n    b, err = structs.NewBitmap(1024)\n    if err != nil { return err }\n}","typeGuard":"func nonNilBitmap(b structs.Bitmap) (structs.Bitmap, error) {\n    if b == nil {\n        return structs.NewBitmap(1024)\n    }\n    return b, nil\n}","tryCatchPattern":"copy, err := b.Copy()\nif err != nil && strings.Contains(err.Error(), \"nil Bitmap\") {\n    // treat as uninitialized; initialize or skip\n}","preventionTips":["Only copy Bitmaps produced by NewBitmap or Copy.","Never rely on the Go zero value of a Bitmap struct field.","Initialize bitmaps when constructing NetworkResource in tests."],"tags":["nomad","bitmap","nil-pointer","copy"],"backgroundTag":"nil-reference","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"}