{"record":{"id":"33852010b9b2bb5a","repo":"hyperledger/fabric","slug":"could-not-get-last-config-for-channel-s","errorCode":null,"errorMessage":"could not get last config for channel %s","messagePattern":"could not get last config for channel (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/support/config/support.go","lineNumber":57,"sourceCode":"\n// DiscoverySupport implements support that is used for service discovery\n// that is related to configuration\ntype DiscoverySupport struct {\n\tCurrentConfigGetter\n}\n\n// NewDiscoverySupport creates a new DiscoverySupport\nfunc NewDiscoverySupport(getLastConfig CurrentConfigGetter) *DiscoverySupport {\n\treturn &DiscoverySupport{\n\t\tCurrentConfigGetter: getLastConfig,\n\t}\n}\n\n// Config returns the channel's configuration\nfunc (s *DiscoverySupport) Config(channel string) (*discovery.ConfigResult, error) {\n\tconfig := s.GetCurrConfig(channel)\n\tif config == nil {\n\t\treturn nil, errors.Errorf(\"could not get last config for channel %s\", channel)\n\t}\n\n\tif err := ValidateConfig(config); err != nil {\n\t\treturn nil, errors.WithMessage(err, \"config is invalid\")\n\t}\n\n\tres := &discovery.ConfigResult{\n\t\tMsps:     make(map[string]*msp.FabricMSPConfig),\n\t\tOrderers: make(map[string]*discovery.Endpoints),\n\t}\n\tordererGrp := config.ChannelGroup.Groups[channelconfig.OrdererGroupKey].Groups\n\tappGrp := config.ChannelGroup.Groups[channelconfig.ApplicationGroupKey].Groups\n\n\tvar globalEndpoints []string\n\tglobalOrderers := config.ChannelGroup.Values[channelconfig.OrdererAddressesKey]\n\tif globalOrderers != nil {\n\t\tordererAddressesConfig := &common.OrdererAddresses{}\n\t\tif err := proto.Unmarshal(globalOrderers.Value, ordererAddressesConfig); err != nil {","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/support/config/support.go#L39-L75","documentation":"DiscoverySupport.Config builds the channel's config result from the peer's current channel config. If GetCurrConfig(channel) returns nil — the service holds no last-config for that channel — it cannot produce a ConfigResult and returns this error.","triggerScenarios":"A discovery config query for a channel the peer hasn't joined or whose config hasn't been loaded into the config service; also hit in unit tests when the fake GetCurrConfig returns nil.","commonSituations":"Config query issued immediately after channel creation before the peer processes the config block; peer joined to a different channel than requested; name typo in the discovery request.","solutions":["Wait until the peer has committed the channel's latest config block, then retry the config query","Verify the channel name and that the peer joined it (peer channel list)","Check peer logs for ledger/config load failures that would leave GetCurrConfig nil"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// query after the peer reports the channel as active\nstatus := getChannelStatus(peerEndpoint, channelID)\nif status != \"active\" {\n    return fmt.Errorf(\"channel %s not active yet\", channelID)\n}","typeGuard":null,"tryCatchPattern":"var res *discovery.ConfigResult\nerr := retry.Do(func() error {\n    r, err := client.Send(ctx, req)\n    if err != nil && strings.Contains(err.Error(), \"could not get last config\") {\n        return retry.RetryableError(err) // config may still be loading\n    }\n    res = r\n    return err\n})","preventionTips":["Delay config queries until after the peer commits the channel config block","Verify channel name and peer membership before querying","Alert on peer ledger/config load failures"],"tags":["fabric","discovery","config","channel"],"backgroundTag":"channel-not-found","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"}