{"record":{"id":"f4a967016720137e","repo":"apache/hadoop","slug":"invalid-registration-no-block-pool-specified","errorCode":null,"errorMessage":"Invalid registration, no block pool specified {}","messagePattern":"Invalid registration, no block pool specified (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/MembershipState.java","lineNumber":259,"sourceCode":"   */\n  @Override\n  public void validate() {\n    super.validate();\n    if (getNameserviceId() == null || getNameserviceId().length() == 0) {\n      throw new IllegalArgumentException(\n          ERROR_MSG_NO_NS_SPECIFIED + this);\n    }\n    if (getWebAddress() == null || getWebAddress().length() == 0) {\n      throw new IllegalArgumentException(\n          ERROR_MSG_NO_WEB_ADDR_SPECIFIED + this);\n    }\n    if (getRpcAddress() == null || getRpcAddress().length() == 0) {\n      throw new IllegalArgumentException(\n          ERROR_MSG_NO_RPC_ADDR_SPECIFIED + this);\n    }\n    if (!isBadState() &&\n        (getBlockPoolId().isEmpty() || getBlockPoolId().length() == 0)) {\n      throw new IllegalArgumentException(\n          ERROR_MSG_NO_BP_SPECIFIED + this);\n    }\n  }\n\n\n  /**\n   * Overrides the cached getBlockPoolId() with an update. The state will be\n   * reset when the cache is flushed\n   *\n   * @param newState Service state of the namenode.\n   */\n  public void overrideState(FederationNamenodeServiceState newState) {\n    this.setState(newState);\n  }\n\n  /**\n   * Sort by nameservice, namenode, and router.\n   *","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/store/records/MembershipState.java#L241-L277","documentation":"MembershipState.validate() requires a block pool id unless the membership is in a 'bad' state — isBadState() is true only for EXPIRED or UNAVAILABLE. For an ACTIVE/STANDBY/OBSERVER registration, an empty blockPoolId throws IllegalArgumentException(ERROR_MSG_NO_BP_SPECIFIED + this). The BPID comes from the Namenode at registration and identifies the namespace's block pool to the Router.","triggerScenarios":"Registering a membership in a live state (ACTIVE/STANDBY/OBSERVER) without setBlockPoolId: programmatic registrations or migrations that omitted it; a resolver/heartbeat that could not obtain the BPID from the Namenode. Note the code first calls getBlockPoolId().isEmpty() — a null BPID can NPE before this message, so an empty string is the classic trigger.","commonSituations":"Custom tooling/tests writing membership records with only addresses; state store row migrations dropping the bpId column; heartbeats from configurations where the BPID lookup failed. EXPIRED/UNAVAILABLE members intentionally bypass this check.","solutions":["When building MembershipState in code, set the block pool id obtained from the Namenode (.getBlockPoolId of the NNInfo) alongside nsId/rpc/web addresses.","Prefer the automatic heartbeat path — it fills the BPID from the real Namenode.","If the record is stale, mark it EXPIRED/UNAVAILABLE or remove it, since bad states are exempt from the BPID requirement.","Check the record dump in the message for the state and missing field."],"exampleFix":"// before: live-state registration without BPID\nm.setNameserviceId(\"ns1\");\nm.setRpcAddress(\"nn1:8020\");\nm.setWebAddress(\"nn1:9870\");\nm.setState(ACTIVE);\nstore.put(m); // throws: no block pool specified\n\n// after: include the block pool id from the Namenode\nm.setBlockPoolId(\"BP-1542879483-10.1.1.1-1680000000000\");\nstore.put(m);","handlingStrategy":"validation","validationCode":"// BPID is required for live states; EXPIRED/UNAVAILABLE are exempt\nif (!m.isBadStateFlag() /* state != EXPIRED && != UNAVAILABLE */\n    && (m.getBlockPoolId() == null || m.getBlockPoolId().isEmpty())) {\n  throw new IllegalArgumentException(\"block pool id required for state \" + m.getState());\n}","typeGuard":"boolean passesBpidRule(MembershipState m) {\n  FederationNamenodeServiceState s = m.getState();\n  if (s == FederationNamenodeServiceState.EXPIRED\n      || s == FederationNamenodeServiceState.UNAVAILABLE) {\n    return true; // exempt\n  }\n  return m.getBlockPoolId() != null && !m.getBlockPoolId().isEmpty();\n}","tryCatchPattern":"try {\n  store.put(membership);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"no block pool specified\")) {\n    // either fetch the BPID from the Namenode, or mark the record EXPIRED/UNAVAILABLE\n    throw new IllegalStateException(\"Registration missing block pool id for live state\", e);\n  }\n  throw e;\n}","preventionTips":["Populate setBlockPoolId from the Namenode's reported BPID whenever constructing membership records programmatically.","For stale members, mark them EXPIRED/UNAVAILABLE — those states legitimately bypass the BPID check.","Note getBlockPoolId().isEmpty() NPEs on null: never leave the BPID null in custom record code."],"tags":["hdfs","router-based-federation","state-store","membership","record-validation","block-pool"],"backgroundTag":"invalid-service-registration","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}