{"record":{"id":"3611cb50bad389e7","repo":"golang/go","slug":"internal-error-unsupported-comdat-selection-strat","errorCode":null,"errorMessage":"internal error: unsupported COMDAT selection strategy found in path=%s sec=%d strategy=%d idx=%d, please file a bug","messagePattern":"internal error: unsupported COMDAT selection strategy found in path=(.+?) sec=(.+?) strategy=(.+?) idx=(.+?), please file a bug","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/link/internal/loadpe/ldpe.go","lineNumber":806,"sourceCode":"\t\tif pesym.StorageClass != uint8(IMAGE_SYM_CLASS_STATIC) {\n\t\t\tcontinue\n\t\t}\n\t\t// This symbol corresponds to a COMDAT section. Read the\n\t\t// aux data for it.\n\t\tauxsymp, err := state.f.COFFSymbolReadSectionDefAux(i)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to read aux info for section def symbol %d %s: pe.COFFSymbolReadComdatInfo returns %v\", i, symname, err)\n\t\t}\n\t\tif auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_SAME_SIZE {\n\t\t\t// This is supported.\n\t\t} else if auxsymp.Selection == pe.IMAGE_COMDAT_SELECT_ANY {\n\t\t\t// Also supported.\n\t\t\tstate.comdats[uint16(pesym.SectionNumber-1)] = int64(-1)\n\t\t} else {\n\t\t\t// We don't support any of the other strategies at the\n\t\t\t// moment. I suspect that we may need to also support\n\t\t\t// \"associative\", we'll see.\n\t\t\treturn fmt.Errorf(\"internal error: unsupported COMDAT selection strategy found in path=%s sec=%d strategy=%d idx=%d, please file a bug\", state.pn, auxsymp.SecNum, auxsymp.Selection, i)\n\t\t}\n\t}\n\treturn nil\n}\n\n// LookupBaseFromImport examines the symbol \"s\" to see if it\n// corresponds to an import symbol (name of the form \"__imp_XYZ\") and\n// if so, it looks up the underlying target of the import symbol and\n// returns it. An error is returned if the symbol is of the form\n// \"__imp_XYZ\" but no XYZ can be found.\nfunc LookupBaseFromImport(s loader.Sym, ldr *loader.Loader, arch *sys.Arch) (loader.Sym, error) {\n\tsname := ldr.SymName(s)\n\tif !strings.HasPrefix(sname, \"__imp_\") {\n\t\treturn 0, nil\n\t}\n\tbasename := sname[len(\"__imp_\"):]\n\tif arch.Family == sys.I386 && basename[0] == '_' {\n\t\tbasename = basename[1:] // _Name => Name","sourceCodeStart":788,"sourceCodeEnd":824,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/link/internal/loadpe/ldpe.go#L788-L824","documentation":"The Go linker encountered a COMDAT section with a selection strategy that is not supported. COMDAT sections use a selection strategy to decide how to merge duplicate definitions across object files. The Go linker only supports IMAGE_COMDAT_SELECT_ANY (pick any copy) and IMAGE_COMDAT_SELECT_SAME_SIZE (duplicates must have the same size). Other strategies such as EXACT_MATCH, ASSOCIATIVE, LARGEST, or EXPAND_POINTER are not implemented and trigger this internal error.","triggerScenarios":"Fires in `preprocessSymbols` at ldpe.go:802-806 when the auxiliary symbol record's `Selection` field is neither IMAGE_COMDAT_SELECT_SAME_SIZE nor IMAGE_COMDAT_SELECT_ANY. This is the code path reached only after successfully reading the aux record (past the check at line 794). The comment in source explicitly notes that 'associative' strategy may need future support.","commonSituations":"Linking C++ code via cgo on Windows that uses template instantiations or inline functions placed in COMDAT sections with EXACT_MATCH or LARGEST strategies. Using LLVM/Clang-produced object files that default to stricter COMDAT strategies than MSVC. C++ libraries with `__declspec(selectany)` or similar that compile to non-ANY/non-SAME_SIZE COMDAT. Debug builds of C code that emit COMDAT sections for incremental linking features.","solutions":["Recompile the C/C++ code with compiler flags that force simpler COMDAT strategies — e.g., with MSVC use `/Gy-` to disable function-level linking, or with Clang use `-fno-comdat-statistics` or equivalent.","If using C++, consider rewriting the problematic code in C (which rarely uses COMDAT) or isolating it into a precompiled static library that Go links against rather than compiling directly.","Update Go to the latest version — newer releases may add support for additional COMDAT strategies (check release notes and the Go issue tracker).","File a bug at https://go.dev/issue including the strategy number from the error message and the object file, as the source comment explicitly requests ('please file a bug').","As a workaround, use `-ldflags=-linkmode=external` to delegate linking to an external linker (gcc/ld) that handles all COMDAT strategies natively."],"exampleFix":"# Use external linker mode to bypass Go's internal COMDAT limitations\ngo build -ldflags='-linkmode=external' ./...\n\n# Or recompile C code to avoid aggressive COMDAT strategies\n# With Clang:\nclang -c -fmerge-all-constants file.c -o file.o","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["When linking C++ via cgo on Windows, prefer -ldflags=-linkmode=external to let the system linker handle complex COMDAT strategies.","Avoid C++ templates and inline functions in cgo boundary code — they generate complex COMDAT sections.","Keep C/C++ interop code simple: prefer plain C with standard function definitions.","Test cgo builds with different compiler optimization levels; -O0 may produce simpler COMDAT sections."],"tags":["linker","pe","coff","comdat","windows","cgo","internal-error"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}