I don’t know how you are processing the bias but you would either have to scale it with 1/C if you are using the bias directly in the grouped conv or you could add it after the reduction as seen here:
import torch
import torch.nn as nn

N, C, H, W = 1, 4, 24, 24

for _ in range(100):
    N, C, H, W = torch.randint(1, 100, (4,))
    
    x = torch.rand(N, C, H, W)
    
    out_channels = 8
    kw = 3
    conv = nn.Conv2d(C, out_channels, kw, 1, 1, bias=True)
    out = conv(x)
    #print(out.shape)
    # > torch.Size([1, 8, 24, 24])
    
    conv_grouped = nn.Conv2d(C, C*out_channels, kw, 1, 1, groups=C, bias=True)
    with torch.no_grad():
        conv_grouped.weight.copy_(conv.weight.permute(1, 0, 2, 3).reshape(C*out_channels, 1, kw, kw))
        conv_grouped.bias.copy_(conv.bias.repeat(C) / C) # scale bias, since it's added after the channel reduction in the plain conv
    out_grouped = conv_grouped(x)
    #print(out_grouped.shape)
    # > torch.Size([1, 32, 24, 24])
    
    out_grouped = out_grouped.view(N, C, out_channels, H, W).permute(0, 2, 1, 3, 4).reshape(N, C*out_channels, H, W)
    
    # manually reduce
    idx = torch.arange(out_channels)
    idx = torch.repeat_interleave(idx, C)
    idx = idx[None, :, None, None].expand(N, -1, H, W)
    out_grouped_reduced = torch.zeros_like(out)
    out_grouped_reduced.scatter_add_(dim=1, index=idx, src=out_grouped)
    
    # alternatively add the bias after the reduction
    #out_grouped_reduced = out_grouped_reduced + conv.bias[None, :, None, None].expand_as(out_grouped_reduced)
    
    # check error
    print(torch.allclose(out_grouped_reduced, out, atol=5e-6), (out_grouped_reduced - out).abs().max())