{"record":{"id":"67f3111368798199","repo":"hyperledger/fabric","slug":"config-id-illegal-cannot-be-empty","errorCode":null,"errorMessage":"config ID illegal, cannot be empty","messagePattern":"config ID illegal, cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/configtx/validator.go","lineNumber":52,"sourceCode":"type ValidatorImpl struct {\n\tchannelID   string\n\tsequence    uint64\n\tconfigMap   map[string]comparable\n\tconfigProto *cb.Config\n\tnamespace   string\n\tpm          policies.Manager\n}\n\n// validateConfigID makes sure that the config element names (ie map key of\n// ConfigGroup) comply with the following restrictions\n//  1. Contain only ASCII alphanumerics, dots '.', dashes '-'\n//  2. Are shorter than 250 characters.\n//  3. Are not the strings \".\" or \"..\".\nfunc validateConfigID(configID string) error {\n\tre, _ := regexp.Compile(configAllowedChars)\n\t// Length\n\tif len(configID) <= 0 {\n\t\treturn errors.New(\"config ID illegal, cannot be empty\")\n\t}\n\tif len(configID) > MaxLength {\n\t\treturn errors.Errorf(\"config ID illegal, cannot be longer than %d\", MaxLength)\n\t}\n\t// Illegal name\n\tif _, ok := illegalNames[configID]; ok {\n\t\treturn errors.Errorf(\"name '%s' for config ID is not allowed\", configID)\n\t}\n\t// Illegal characters\n\tmatched := re.FindString(configID)\n\tif len(matched) != len(configID) {\n\t\treturn errors.Errorf(\"config ID '%s' contains illegal characters\", configID)\n\t}\n\n\treturn nil\n}\n\n// ValidateChannelID makes sure that proposed channel IDs comply with the","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/configtx/validator.go#L34-L70","documentation":"validateConfigID rejects configuration item IDs (group/policy/value keys) that do not conform to Fabric's naming rules. An empty string is immediately illegal because every config element must have a non-empty identifier. This prevents ambiguous config paths in the channel configuration tree.","triggerScenarios":"Building a ConfigUpdate whose config group/value/policy map key is the empty string; programmatically constructing config groups with an unset Name/ID field.","commonSituations":"Hand-writing config update JSON/YAML where a key was omitted; a script generating config from a template with an unfilled variable; merging config trees where an element lost its ID.","solutions":["Set a non-empty ID for every config group, value, and policy in the update","Validate all config keys with validateConfigID-style checks before submitting the update","Fix the generating script/template so the ID variable is populated","Use configtxlator to decode and inspect the update to find the offending empty key"],"exampleFix":"// before\ngroup.Groups[\"\"] = &cb.ConfigGroup{}\n// after\nif name == \"\" {\n    return errors.New(\"config group name must not be empty\")\n}\ngroup.Groups[name] = &cb.ConfigGroup{}","handlingStrategy":"validation","validationCode":"if configID == \"\" {\n    return errors.New(\"config ID must not be empty\")\n}","typeGuard":"func validConfigID(id string) bool {\n    return id != \"\" && len(id) <= 250 &&\n        id != \".\" && id != \"..\" &&\n        strings.TrimLeft(id, \"abcdefghijklmnopqrstuvwxyz0123456789.-\") == \"\"\n}","tryCatchPattern":"if err := validateName(id); err != nil {\n    return fmt.Errorf(\"invalid config ID: %w\", err)\n}","preventionTips":["Never emit empty keys into config group/value/policy maps","Unset-template variables should fail the build, not produce empty IDs","Decode submitted updates with configtxlator to inspect all keys","Add unit tests asserting no generated config key is empty"],"tags":["go","fabric","config","validation","naming"],"backgroundTag":"invalid-config-value","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}