{"record":{"id":"8986b90871f37eee","repo":"apache/hadoop","slug":"s-is-not-appendable-because-append-non-existed-ob-8986b9","errorCode":null,"errorMessage":"%s is not appendable because append non-existed object with zero byte is not supported.","messagePattern":"(.+?) is not appendable because append non-existed object with zero byte is not supported\\.","errorType":"exception","errorClass":"NotAppendableException","httpStatus":null,"severity":"error","filePath":"hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/tos/TOS.java","lineNumber":478,"sourceCode":"  @Override\n  public byte[] append(String key, InputStreamProvider streamProvider, long contentLength) {\n    if (bucketInfo.isDirectory()) {\n      return hnsAppend(key, streamProvider, contentLength);\n    } else {\n      return fnsAppend(key, streamProvider, contentLength);\n    }\n  }\n\n  private byte[] hnsAppend(String key, InputStreamProvider streamProvider, long contentLength) {\n    checkAvailableClient();\n\n    long offset = 0;\n    String preCrc64;\n\n    TosObjectInfo obj = innerHead(key);\n    if (obj == null) {\n      if (contentLength == 0) {\n        throw new NotAppendableException(String.format(\n            \"%s is not appendable because append non-existed object with \"\n                + \"zero byte is not supported.\", key));\n      }\n\n      // In HNS, append non-existed object is not allowed. Pre-create an empty object before\n      // performing appendObject.\n      PutObjectOutput res = client.put(bucket, key, () -> EMPTY_STREAM, 0, defaultAcl);\n      preCrc64 = res.getHashCrc64ecma();\n    } else {\n      if (contentLength == 0) {\n        return obj.checksum();\n      }\n      offset = obj.size();\n      preCrc64 = obj.crc64ecma();\n    }\n\n    AppendObjectOutput res =\n        client.appendObject(bucket, key, streamProvider, offset, contentLength, preCrc64,","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/apache/hadoop/blob/2add9630210752f88ceb1bb74eb65e37bf41da8e/hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/tos/TOS.java#L460-L496","documentation":"In HNS (directory-bucket) mode, TOS.append routes to hnsAppend. TOS forbids appending to a non-existent object, and a zero-byte append cannot pre-create one (the code only pre-creates via putObject when contentLength > 0), so append(key, empty) on a missing key throws NotAppendableException (\"<key> is not appendable because append non-existed object with zero byte is not supported.\"), a RuntimeException documented on ObjectStorage.append.","triggerScenarios":"append(key, new byte[0]) on a key that does not exist in an HNS/directory bucket; opening an append stream and closing it without writing any bytes; jobs that 'create' empty files purely via append.","commonSituations":"Jobs creating empty markers then appending later; manifest/commit writers opening streams for zero-length files; behavior differences between FNS (general-purpose) and HNS directory buckets.","solutions":["Skip the append when contentLength == 0 and the object doesn't exist; create the marker with put(key, emptyStream, 0) instead","head(key) first: if null and the payload is empty, avoid calling append","Buffer data so every append carries at least one byte","If the file must exist, write it through the normal create path rather than append"],"exampleFix":"// before\nstorage.append(key, new byte[0]);\n\n// after\nif (storage.head(key) == null && data.length == 0) {\n  storage.put(key, () -> new ByteArrayInputStream(data), 0); // create empty marker\n  return;\n}\nstorage.append(key, data);","handlingStrategy":"validation","validationCode":"if (storage.head(key) == null && data.length == 0) {\n  // zero-byte append cannot create an object in HNS mode; use put instead\n  storage.put(key, () -> new ByteArrayInputStream(data), 0);\n  return;\n}\nstorage.append(key, data);","typeGuard":null,"tryCatchPattern":"try {\n  storage.append(key, data);\n} catch (NotAppendableException e) {\n  if (data.length == 0 && storage.head(key) == null) {\n    storage.put(key, () -> new ByteArrayInputStream(data), 0);\n  } else {\n    throw e;\n  }\n}","preventionTips":["Never append zero bytes to a non-existent key","Create empty markers with put(), not append()","Buffer writes so appends always carry bytes"],"tags":["hadoop-tos","volcengine-tos","append","hns","directory-bucket"],"backgroundTag":"object-not-appendable","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}