apache/hadoop · error · NotAppendableException

%s is not appendable.

Error message

%s is not appendable.

What it means

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.

Source

Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/tos/TOS.java:508

      }
      offset = obj.size();
      preCrc64 = obj.crc64ecma();
    }

    AppendObjectOutput res =
        client.appendObject(bucket, key, streamProvider, offset, contentLength, preCrc64,
            defaultAcl);
    return ObjectInfo.isDir(key) ? Constants.MAGIC_CHECKSUM :
        parseChecksum(res.getRequestInfo().getHeader(), checksumInfo);
  }

  private byte[] fnsAppend(String key, InputStreamProvider streamProvider, long contentLength) {
    checkAvailableClient();

    TosObjectInfo obj = innerHead(key);
    if (obj != null) {
      if (!obj.appendable()) {
        throw new NotAppendableException(String.format("%s is not appendable.", key));
      }
      if (contentLength == 0) {
        return obj.checksum();
      }
    } else if (contentLength == 0) {
      throw new NotAppendableException(String.format("%s is not appendable because append"
          + " non-existed object with zero byte is not supported.", key));
    }

    long offset = obj == null ? 0 : obj.size();
    String preCrc64 = obj == null ? null : obj.crc64ecma();
    AppendObjectOutput res;
    try {
      res = client.appendObject(bucket, key, streamProvider, offset, contentLength, preCrc64,
          defaultAcl);
    } catch (TosServerException e) {
      if (e.getStatusCode() == 409 && APPEND_NOT_APPENDABLE.equals(e.getEc())) {
        throw new NotAppendableException(String.format("%s is not appendable.", key));

View on GitHub (pinned to 2add963021)

Solutions

  1. Rewrite the object from scratch through the append path if append semantics are required
  2. Before calling append, treat any existing object written by a normal PUT as non-appendable and fail with a clear message
  3. Avoid FileSystem.append on tos:// for files not created appendable; use copy-on-write or part-file schemes instead

Example fix

// before
storage.append(key, data);

// after: fail fast with actionable context
try {
  storage.append(key, data);
} catch (NotAppendableException e) {
  throw new IOException(key
      + " was created by a normal upload and cannot be appended;"
      + " rewrite it via the append/create path instead", e);
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  storage.append(key, data);
} catch (NotAppendableException e) {
  throw new IOException(key
      + " was created by a normal upload and cannot be appended;"
      + " rewrite it via the append path instead", e);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/b6666fbd86bbd922. Report an issue: GitHub.