hyperledger/fabric · error

channel participation API is disabled

Error message

channel participation API is disabled

What it means

The channel participation API HTTP handler is guarded by a configuration flag; when channel participation (the REST join/remove/list endpoints) is disabled in the orderer config, ServeHTTP rejects every request with 503 and this error. The route still exists but is intentionally inert.

Source

Thrown at orderer/common/channelparticipation/restapi.go:260

	//    '400':
	//      description: Bad request.
	//    '404':
	//      description: The channel or block does not exist.

	handler.router.HandleFunc(urlWithChannelAndBlockIDKey, handler.serveFetchBlock).Methods(http.MethodGet)

	handler.router.HandleFunc(urlWithChannelAndBlockIDKey, handler.serveNotAllowed)
	handler.router.HandleFunc(urlWithChannelIDKey, handler.serveNotAllowed)
	handler.router.HandleFunc(URLBaseV1Channels, handler.serveNotAllowed)

	handler.router.HandleFunc(URLBaseV1, handler.redirectBaseV1).Methods(http.MethodGet)

	return handler
}

func (h *HTTPHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	if !h.config.Enabled {
		err := errors.New("channel participation API is disabled")
		h.sendResponseJsonError(resp, http.StatusServiceUnavailable, err)
		return
	}

	h.router.ServeHTTP(resp, req)
}

// List all channels
func (h *HTTPHandler) serveListAll(resp http.ResponseWriter, req *http.Request) {
	_, err := negotiateContentType(req) // Only application/json responses for now
	if err != nil {
		h.sendResponseJsonError(resp, http.StatusNotAcceptable, err)
		return
	}
	channelList := h.registrar.ChannelList()
	if channelList.SystemChannel != nil && channelList.SystemChannel.Name != "" {
		channelList.SystemChannel.URL = path.Join(URLBaseV1Channels, channelList.SystemChannel.Name)
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set channelParticipation.enabled: true in orderer.yaml (or env OVERORDERER... CHANNELPARTICIPATION_ENABLED equivalent) and restart the orderer
  2. Use osnadmin with the orderer's admin endpoint/port that actually serves the participation API
  3. If the orderer manages channels via the legacy system-chain/Jaeger path, use the appropriate channel-creation flow instead of the participation API

Example fix

// before (orderer.yaml)
ChannelParticipation:
  Enabled: false
// after
ChannelParticipation:
  Enabled: true
  MaxRequestBodySize: 1024 * 1024
Defensive patterns

Strategy: validation

Validate before calling

// before calling the API, verify the orderer config flag
// orderer.yaml: ChannelParticipation.Enabled must be true
cfgEnabled := os.Getenv("ORDERER_CHANNELPARTICIPATION_ENABLED") == "true"
if !cfgEnabled { return errors.New("participation API disabled on this orderer") }

Try / catch

resp, err := http.Post(url, "", body)
if resp != nil && resp.StatusCode == http.StatusServiceUnavailable {
	return errors.New("channel participation API is disabled; enable ChannelParticipation.Enabled and restart orderer")
}

Prevention

When it happens

Trigger: Sending any request to the orderer's /participation endpoints (join, remove, list) while GENERAL.CHANNELPARTICIPATION.ENABLED is false in orderer.yaml.

Common situations: Admin forgot to enable the participation API before running osnadmin; connecting an automation tool (osnadmin channel join) to an orderer whose config predates or omits the feature; Docker image/env not passing CHANNELPARTICIPATION.ENABLED=true.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/e2a3e5f6c19f0669. Report an issue: GitHub.