{"record":{"id":"b6666fbd86bbd922","repo":"apache/hadoop","slug":"s-is-not-appendable","errorCode":null,"errorMessage":"%s is not appendable.","messagePattern":"(.+?) is not appendable\\.","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":508,"sourceCode":"      }\n      offset = obj.size();\n      preCrc64 = obj.crc64ecma();\n    }\n\n    AppendObjectOutput res =\n        client.appendObject(bucket, key, streamProvider, offset, contentLength, preCrc64,\n            defaultAcl);\n    return ObjectInfo.isDir(key) ? Constants.MAGIC_CHECKSUM :\n        parseChecksum(res.getRequestInfo().getHeader(), checksumInfo);\n  }\n\n  private byte[] fnsAppend(String key, InputStreamProvider streamProvider, long contentLength) {\n    checkAvailableClient();\n\n    TosObjectInfo obj = innerHead(key);\n    if (obj != null) {\n      if (!obj.appendable()) {\n        throw new NotAppendableException(String.format(\"%s is not appendable.\", key));\n      }\n      if (contentLength == 0) {\n        return obj.checksum();\n      }\n    } else if (contentLength == 0) {\n      throw new NotAppendableException(String.format(\"%s is not appendable because append\"\n          + \" non-existed object with zero byte is not supported.\", key));\n    }\n\n    long offset = obj == null ? 0 : obj.size();\n    String preCrc64 = obj == null ? null : obj.crc64ecma();\n    AppendObjectOutput res;\n    try {\n      res = client.appendObject(bucket, key, streamProvider, offset, contentLength, preCrc64,\n          defaultAcl);\n    } catch (TosServerException e) {\n      if (e.getStatusCode() == 409 && APPEND_NOT_APPENDABLE.equals(e.getEc())) {\n        throw new NotAppendableException(String.format(\"%s is not appendable.\", key));","sourceCodeStart":490,"sourceCodeEnd":526,"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#L490-L526","documentation":"In FNS (general-purpose bucket) mode, fnsAppend first heads the object; if it exists but was not created as an appendable object (it was written by a normal PUT or multipart upload), the connector throws NotAppendableException(\"<key> is not appendable.\"). Only objects originally created via appendObject can be appended, matching TOS semantics.","triggerScenarios":"append(key, ...) where key was previously written by the regular write path (put/multipart upload), then something calls append on it — e.g. FileSystem.append() on an existing tos:// file created by a normal write job.","commonSituations":"Calling append() on files created by the standard output stream; mixing write modes on the same key across jobs; assuming S3/HDFS-like append semantics where any file can be appended.","solutions":["Rewrite the object from scratch through the append path if append semantics are required","Before calling append, treat any existing object written by a normal PUT as non-appendable and fail with a clear message","Avoid FileSystem.append on tos:// for files not created appendable; use copy-on-write or part-file schemes instead"],"exampleFix":"// before\nstorage.append(key, data);\n\n// after: fail fast with actionable context\ntry {\n  storage.append(key, data);\n} catch (NotAppendableException e) {\n  throw new IOException(key\n      + \" was created by a normal upload and cannot be appended;\"\n      + \" rewrite it via the append/create path instead\", e);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  storage.append(key, data);\n} catch (NotAppendableException e) {\n  throw new IOException(key\n      + \" was created by a normal upload and cannot be appended;\"\n      + \" rewrite it via the append path instead\", e);\n}","preventionTips":["Do not call append() on objects written by the normal put/multipart path","Use one write mode per key for the object's lifetime","Prefer part-file or copy-on-write patterns over appending existing objects"],"tags":["hadoop-tos","volcengine-tos","append","fns","object-semantics"],"backgroundTag":"object-not-appendable","analyzedSha":"2add9630210752f88ceb1bb74eb65e37bf41da8e","analyzedAt":"2026-08-22T19:55:07.957Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}