nathanmarz/storm · error · RuntimeException

Version already exists or data already exists

Error message

Version already exists or data already exists

What it means

VersionedStore.createVersion computes the path for a requested version and refuses it if that version already appears in getAllVersions() — i.e. a version directory/token already exists in the store. It throws RuntimeException to protect against overwriting an existing snapshot/transaction version.

Solutions

  1. Check existing versions first and pick a new version: if (store.getAllVersions().contains(v)) v = nextFreeVersion().
  2. On concurrent writers, derive the version from a shared monotonic source (zookeeper transaction id) so attempts don't collide.
  3. Clean up failed/incomplete versions (store.failVersion(path) or delete leftover dirs) before retrying the same version.
  4. If the existing version is a stale leftover of the same data, delete the directory and recreate.

Example fix

// before
String path = store.createVersion(txid); // throws if txid already committed
// after
if (store.getAllVersions().contains(txid)) {
    LOG.info("Version " + txid + " already committed, skipping");
    return;
}
String path = store.createVersion(txid);
Defensive patterns

Strategy: validation

Validate before calling

if (store.getAllVersions().contains(txid)) {
    throw new IllegalStateException("Version " + txid + " already exists; skipping or choose a new version");
}

Try / catch

try {
    String path = store.createVersion(txid);
} catch (RuntimeException e) {
    if (e.getMessage().contains("already exists")) {
        // treat as already-committed, recover idempotently
    } else throw e;
}

Prevention

When it happens

Trigger: Calling createVersion(long) (or the Long overload that delegates) with a version number previously created, or creating the same version concurrently from two processes/threads; retrying a create after a previous partially-successful attempt left the version directory on disk.

Common situations: Two workers or a failed-then-retried job both try to commit the same transaction id to a shared HDFS/state store; clock-derived or counter-derived versions reused after a crash; replaying a job without cleaning the store directory.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12). Data as JSON: /api/errors/c262481397350854. Report an issue: GitHub.

Appendix: source

Thrown at storm-core/src/jvm/backtype/storm/utils/VersionedStore.java:85

        for(Long v: all) {
            if(v <= maxVersion) return v;
        }
        return null;
    }

    public String createVersion() throws IOException {
        Long mostRecent = mostRecentVersion();
        long version = Time.currentTimeMillis();
        if(mostRecent!=null && version <= mostRecent) {
            version = mostRecent + 1;
        }
        return createVersion(version);
    }

    public String createVersion(long version) throws IOException {
        String ret = versionPath(version);
        if(getAllVersions().contains(version))
            throw new RuntimeException("Version already exists or data already exists");
        else
            return ret;
    }

    public void failVersion(String path) throws IOException {
        deleteVersion(validateAndGetVersion(path));
    }

    public void deleteVersion(long version) throws IOException {
        File versionFile = new File(versionPath(version));
        File tokenFile = new File(tokenPath(version));
        
        if(versionFile.exists()) {
            FileUtils.forceDelete(versionFile);
        }
        if(tokenFile.exists()) {
            FileUtils.forceDelete(tokenFile);
        }        

View on GitHub (pinned to cdb116e942)