{"record":{"id":"4d186fff60113311","repo":"hyperledger/fabric","slug":"missing-block-id","errorCode":null,"errorMessage":"missing block ID","messagePattern":"missing block ID","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"orderer/common/channelparticipation/restapi.go","lineNumber":536,"sourceCode":"\tchannelID, ok := mux.Vars(req)[channelIDKey]\n\tif !ok {\n\t\terr := errors.New(\"missing channel ID\")\n\t\th.sendResponseJsonError(resp, http.StatusInternalServerError, err)\n\t\treturn \"\", err\n\t}\n\n\tif err := configtx.ValidateChannelID(channelID); err != nil {\n\t\terr = errors.WithMessage(err, \"invalid channel ID\")\n\t\th.sendResponseJsonError(resp, http.StatusBadRequest, err)\n\t\treturn \"\", err\n\t}\n\treturn channelID, nil\n}\n\nfunc (h *HTTPHandler) extractBlockID(req *http.Request, resp http.ResponseWriter) (string, error) {\n\tblockID, ok := mux.Vars(req)[blockIDKey]\n\tif !ok {\n\t\terr := errors.New(\"missing block ID\")\n\t\th.sendResponseJsonError(resp, http.StatusInternalServerError, err)\n\t\treturn \"\", err\n\t}\n\n\tif err := ValidateFetchBlockID(blockID); err != nil {\n\t\terr = errors.WithMessage(err, \"invalid block ID\")\n\t\th.sendResponseJsonError(resp, http.StatusBadRequest, err)\n\t\treturn \"\", err\n\t}\n\treturn blockID, nil\n}\n\nfunc (h *HTTPHandler) sendJoinError(err error, resp http.ResponseWriter) {\n\th.logger.Debugf(\"Failed to JoinChannel: %s\", err)\n\tswitch err {\n\tcase types.ErrSystemChannelExists:\n\t\t// The client is trying to join an app-channel, but the system channel exists: only GET is allowed on app channels.\n\t\th.sendResponseNotAllowed(resp, errors.WithMessage(err, \"cannot join\"), http.MethodGet)","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/channelparticipation/restapi.go#L518-L554","documentation":"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.","triggerScenarios":"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.","commonSituations":"Client code calling /participation/channels/{channelID}/blocks without the trailing block specifier; templated URL not interpolated; proxy truncating the path before the block ID.","solutions":["Add the block specifier to the path, e.g. /participation/channels/mychannel/blocks/latest or /blocks/0 or /blocks/config","Confirm the URL template used by the client fully interpolates the block ID","Check that no middleware or proxy truncates the request path","If validation of the value is the real issue, ensure it passes ValidateFetchBlockID (valid number, 'latest', or 'config')"],"exampleFix":"// before\nGET /participation/channels/mychannel/blocks\n// after\nGET /participation/channels/mychannel/blocks/latest","handlingStrategy":"validation","validationCode":"if (!/^\\d+$|^latest$|^config$/.test(blockID)) throw new Error(`invalid block ID: ${blockID}`);","typeGuard":"function isBlockID(v: unknown): v is string | number {\n  return typeof v === 'number' || (typeof v === 'string' && /^\\d+$|^latest$|^config$/.test(v));\n}","tryCatchPattern":"try {\n  const res = await fetch(`${base}/participation/channels/${cid}/blocks/${blockID}`);\n  const body = await res.json();\n  if (!res.ok) throw new Error(body.error ?? `HTTP ${res.status}`);\n} catch (e) {\n  if (String(e).includes('missing block ID')) console.error('Append a block specifier: <n>, latest, or config');\n  else throw e;\n}","preventionTips":["Interpolate the block specifier into the fetch-block URL template","Only use 'number', 'latest', or 'config' as block IDs (ValidateFetchBlockID)","Log the full request URL on failure to spot truncated paths"],"tags":["http","rest-api","hyperledger-fabric","orderer","routing"],"backgroundTag":"missing-path-parameter","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"}