{"record":{"id":"3e4c46ce890f919f","repo":"apache/hadoop","slug":"filemetadata-not-match-key-key","errorCode":null,"errorMessage":"FileMetadata not match key:\" + key","messagePattern":"FileMetadata not match key:\" \\+ key","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BosNativeFileSystemStore.java","lineNumber":400,"sourceCode":"   * @param key the object key\n   * @param byteRangeStart the start of the byte range\n   * @param byteRangeEnd the end of the byte range\n   * @param meta the file metadata for verification\n   * @return an input stream for reading the range, or null\n   *         if the key is not found\n   * @throws IOException if an I/O error occurs\n   */\n  public InputStream retrieve(\n      String key, long byteRangeStart,\n      long byteRangeEnd, FileMetadata meta)\n      throws IOException {\n    log.debug(\n        \"Getting key: {} from bucket: {} with\"\n            + \" byteRangeStart: {} and\"\n            + \" byteRangeEnd: {}.\",\n        key, bucketName, byteRangeStart, byteRangeEnd);\n    if (meta == null || !meta.getKey().equals(key)) {\n      throw new IOException(\n          \"FileMetadata not match key:\" + key);\n    }\n    GetObjectRequest request =\n        new GetObjectRequest(bucketName, key);\n    // Due to the InvalidRange exception of bos, we\n    // shouldn't set range for empty file\n    if (meta.getLength() != 0) {\n      request.setRange(byteRangeStart, byteRangeEnd);\n    }\n    BosObject object =\n        bosClientProxy.getObject(request);\n    return object.getObjectContent();\n  }\n\n  /**\n   * Converts a prefix to a directory-style key by appending\n   * a trailing delimiter if not already present.\n   *","sourceCodeStart":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BosNativeFileSystemStore.java#L382-L418","documentation":"BosNativeFileSystemStore.retrieve(key, byteRangeStart, byteRangeEnd, meta) enforces an internal invariant before issuing the GET: meta must be non-null and meta.getKey() must equal the requested key, else IOException 'FileMetadata not match key:<key>'. It protects the byte-range read against metadata cached for a different object.","triggerScenarios":"The stream was opened for one key but retrieve receives FileMetadata belonging to another: subclasses/wrappers recycling a metadata instance, hand-built FileMetadata in tests, or a key-normalization difference (trailing slash, encoding) between the metadata key and the fetch key.","commonSituations":"Custom extensions of the store or the input stream passing stale metadata; connector-internal races when a file is replaced between open and read; unit tests constructing FileMetadata directly with a mismatched key.","solutions":["Always obtain FileMetadata via getFileMetadata(key) for the exact same key string used in retrieve","Never reuse one FileMetadata instance across different keys","If you control the boundary, log meta.getKey() versus key where they are produced to find where they diverge"],"exampleFix":"// before\nstore.retrieve(key, start, end, recycledMeta); // from another file\n\n// after\nFileMetadata meta = store.retrieveMetadata(key);\nstore.retrieve(key, start, end, meta);","handlingStrategy":"validation","validationCode":"if (meta == null || !meta.getKey().equals(key)) {\n  meta = store.retrieveMetadata(key); // re-fetch metadata for THIS key\n}\nstore.retrieve(key, start, end, meta);","typeGuard":"static boolean metadataMatches(FileMetadata meta, String key) {\n  return meta != null && meta.getKey() != null && meta.getKey().equals(key);\n}","tryCatchPattern":"catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"FileMetadata not match key\")) {\n    meta = store.retrieveMetadata(key); // invariant broken: refresh and retry once\n  } else { throw e; }\n}","preventionTips":["Fetch FileMetadata per key at open time; never share instances across keys","Keep key strings identical (same normalization) through open and retrieve","Log meta.getKey() vs key at custom boundaries to catch divergence early"],"tags":["bos","metadata-mismatch","invariant","internal-api","hadoop"],"backgroundTag":"metadata-mismatch","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}