hyperledger/fabric · error

missing block ID

Error message

missing block ID

What it means

This error is returned by extractBlockID when the mux path variable holding the block identifier (blockIDKey) is missing from the request, so serveFetchBlock cannot determine which block to fetch. The handler responds with HTTP 500 and a JSON error. It exists because the fetch-block endpoint requires a block specifier such as a number, 'latest', or 'config' in the URL.

Source

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

	channelID, ok := mux.Vars(req)[channelIDKey]
	if !ok {
		err := errors.New("missing channel ID")
		h.sendResponseJsonError(resp, http.StatusInternalServerError, err)
		return "", err
	}

	if err := configtx.ValidateChannelID(channelID); err != nil {
		err = errors.WithMessage(err, "invalid channel ID")
		h.sendResponseJsonError(resp, http.StatusBadRequest, err)
		return "", err
	}
	return channelID, nil
}

func (h *HTTPHandler) extractBlockID(req *http.Request, resp http.ResponseWriter) (string, error) {
	blockID, ok := mux.Vars(req)[blockIDKey]
	if !ok {
		err := errors.New("missing block ID")
		h.sendResponseJsonError(resp, http.StatusInternalServerError, err)
		return "", err
	}

	if err := ValidateFetchBlockID(blockID); err != nil {
		err = errors.WithMessage(err, "invalid block ID")
		h.sendResponseJsonError(resp, http.StatusBadRequest, err)
		return "", err
	}
	return blockID, nil
}

func (h *HTTPHandler) sendJoinError(err error, resp http.ResponseWriter) {
	h.logger.Debugf("Failed to JoinChannel: %s", err)
	switch err {
	case types.ErrSystemChannelExists:
		// The client is trying to join an app-channel, but the system channel exists: only GET is allowed on app channels.
		h.sendResponseNotAllowed(resp, errors.WithMessage(err, "cannot join"), http.MethodGet)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Add the block specifier to the path, e.g. /participation/channels/mychannel/blocks/latest or /blocks/0 or /blocks/config
  2. Confirm the URL template used by the client fully interpolates the block ID
  3. Check that no middleware or proxy truncates the request path
  4. If validation of the value is the real issue, ensure it passes ValidateFetchBlockID (valid number, 'latest', or 'config')

Example fix

// before
GET /participation/channels/mychannel/blocks
// after
GET /participation/channels/mychannel/blocks/latest
Defensive patterns

Strategy: validation

Validate before calling

if (!/^\d+$|^latest$|^config$/.test(blockID)) throw new Error(`invalid block ID: ${blockID}`);

Type guard

function isBlockID(v: unknown): v is string | number {
  return typeof v === 'number' || (typeof v === 'string' && /^\d+$|^latest$|^config$/.test(v));
}

Try / catch

try {
  const res = await fetch(`${base}/participation/channels/${cid}/blocks/${blockID}`);
  const body = await res.json();
  if (!res.ok) throw new Error(body.error ?? `HTTP ${res.status}`);
} catch (e) {
  if (String(e).includes('missing block ID')) console.error('Append a block specifier: <n>, latest, or config');
  else throw e;
}

Prevention

When it happens

Trigger: GET requests to the channel participation fetch-block endpoint whose URL does not contain the block ID path segment, so mux.Vars(req)[blockIDKey] is not present.

Common situations: Client code calling /participation/channels/{channelID}/blocks without the trailing block specifier; templated URL not interpolated; proxy truncating the path before the block ID.

Related errors


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