{"record":{"id":"d8c44712860b6b8a","repo":"hyperledger/fabric","slug":"can-t-read-the-block-v","errorCode":null,"errorMessage":"can't read the block: %v","messagePattern":"can't read the block: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/peer/common/deliverclient.go","lineNumber":75,"sourceCode":"func (d *DeliverClient) seekOldest() error {\n\tenv := seekHelper(d.ChannelID, seekOldest, d.TLSCertHash, d.Signer, d.BestEffort)\n\treturn d.Service.Send(env)\n}\n\nfunc (d *DeliverClient) seekNewest() error {\n\tenv := seekHelper(d.ChannelID, seekNewest, d.TLSCertHash, d.Signer, d.BestEffort)\n\treturn d.Service.Send(env)\n}\n\nfunc (d *DeliverClient) readBlock() (*cb.Block, error) {\n\tmsg, err := d.Service.Recv()\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"error receiving\")\n\t}\n\tswitch t := msg.Type.(type) {\n\tcase *ab.DeliverResponse_Status:\n\t\tlogger.Infof(\"Expect block, but got status: %v\", t)\n\t\treturn nil, errors.Errorf(\"can't read the block: %v\", t)\n\tcase *ab.DeliverResponse_Block:\n\t\tlogger.Infof(\"Received block: %v\", t.Block.Header.Number)\n\t\tif resp, err := d.Service.Recv(); err != nil { // Flush the success message\n\t\t\tlogger.Errorf(\"Failed to flush success message: %s\", err)\n\t\t} else if status := resp.GetStatus(); status != cb.Status_SUCCESS {\n\t\t\tlogger.Errorf(\"Expect status to be SUCCESS, got: %s\", status)\n\t\t}\n\n\t\treturn t.Block, nil\n\tdefault:\n\t\treturn nil, errors.Errorf(\"response error: unknown type %T\", t)\n\t}\n}\n\n// GetSpecifiedBlock gets the specified block from a peer/orderer's deliver\n// service\nfunc (d *DeliverClient) GetSpecifiedBlock(num uint64) (*cb.Block, error) {\n\terr := d.seekSpecified(num)","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/common/deliverclient.go#L57-L93","documentation":"The deliver service returned a status response instead of the requested block. readBlock expects a block, so any non-block status (e.g. FORBIDDEN, NOT_FOUND, BAD_REQUEST, SERVICE_UNAVAILABLE) is reported as \"can't read the block\" with the status detail.","triggerScenarios":"The deliver request was rejected by the server: seeking a block the server won't serve (out of range/pruned ledger), the identity lacks deliver/read ACLs, or the server reports internal unavailability.","commonSituations":"Requesting an old archived block that has been pruned, using a client identity not authorized for the deliver service, seeking a block number beyond the ledger height, orderer unavailable during maintenance.","solutions":["Check the status embedded in the error (e.g. FORBIDDEN vs NOT_FOUND) and address that cause","Verify the requested block number exists (ledger height) and hasn't been pruned","Ensure the client signer has deliver/read permission on the channel","Retry against a different orderer/peer serving the channel"],"exampleFix":"// before\nblock, err := client.GetSpecifiedBlock(num)\n// after\nblock, err := client.GetSpecifiedBlock(num)\nif err != nil && strings.Contains(err.Error(), \"can't read the block\") {\n    log.Fatalf(\"deliver rejected, check status/ACLs: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"// check ledger height before seeking\ninfo, _ := ledgerClient.QueryInfo()\nif num >= info.Height { return errors.New(\"block number beyond ledger height\") }\n// ensure the identity has deliver/read rights on the channel","typeGuard":"if statusResp, ok := msg.Type.(*ab.DeliverResponse_Status); ok {\n    return fmt.Errorf(\"deliver rejected with status %s\", statusResp.Status)\n}","tryCatchPattern":"block, err := client.GetSpecifiedBlock(num)\nif err != nil && strings.Contains(err.Error(), \"can't read the block\") {\n    // inspect embedded status: FORBIDDEN => ACL, NOT_FOUND => pruned/out-of-range\n    return translateDeliverStatus(err)\n}","preventionTips":["Never seek pruned or out-of-range block numbers","Grant the client identity deliver/read privileges","Check server status codes embedded in the error before retrying"],"tags":["fabric","deliver","block-fetch","acl"],"backgroundTag":"deliver-status-rejected","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"}