{"record":{"id":"1b39e1290821194c","repo":"xpipe-io/xpipe","slug":"key-file-is-not-synced","errorCode":null,"errorMessage":"Key file is not synced","messagePattern":"Key file is not synced","errorType":"validation","errorClass":"ValidationException","httpStatus":null,"severity":"error","filePath":"ext/base/src/main/java/io/xpipe/ext/base/identity/SyncedIdentityStore.java","lineNumber":107,"sourceCode":"        return password != null ? password.getValue() : null;\n    }\n\n    @Override\n    public SshIdentityStrategy getSshIdentity() {\n        return sshIdentity != null ? sshIdentity.getValue() : null;\n    }\n\n    @Override\n    public List<DataStoreEntryRef<?>> getDependencies() {\n        return List.of();\n    }\n\n    @Override\n    public void checkComplete() throws ValidationException {\n        super.checkComplete();\n        if (getSshIdentity() instanceof KeyFileStrategy f) {\n            if (!f.getFile().isInDataDirectory()) {\n                throw new ValidationException(\"Key file is not synced\");\n            }\n        }\n    }\n\n    OptionalEncryptedValue<SecretRetrievalStrategy> getEncryptedPassword() {\n        return password;\n    }\n\n    OptionalEncryptedValue<SshIdentityStrategy> getEncryptedSshIdentity() {\n        return sshIdentity;\n    }\n\n    @Override\n    public DataStore withUpdatedPrincipals() {\n        var targetScope = DataStoreAccessScope.getTargetScope(accessScope);\n        if (targetScope != null && targetScope.equals(DataStoreAccessScope.vault())) {\n            targetScope = null;\n        }","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/xpipe-io/xpipe/blob/d85ca821baa46092a320ebb13546d7240adb74f8/ext/base/src/main/java/io/xpipe/ext/base/identity/SyncedIdentityStore.java#L89-L125","documentation":"SyncedIdentityStore.checkComplete() validates SSH identity stores. When the identity strategy is a key file, the file must live inside XPipe's data directory so it can be synced/backed up with the store. A key file stored outside the data directory cannot be synchronized, so validation fails with ValidationException(\"Key file is not synced\").","triggerScenarios":"Calling checkComplete() (directly or via store save/validation) on a SyncedIdentityStore whose getSshIdentity() is a KeyFileStrategy whose getFile().isInDataDirectory() returns false — i.e. the key file path points outside the XPipe data directory.","commonSituations":"Users select a private key from ~/.ssh/ or another home location instead of importing/copying it into the XPipe-managed data directory; identity stores copied from another machine referencing absolute external paths; key files moved or deleted from the data directory.","solutions":["Copy or import the key file into the XPipe data directory and point the identity store at the synced copy","Use XPipe's key-file import UI which automatically copies the key into the data directory instead of referencing the external path","Choose a different identity strategy (e.g. agent-based) that does not require a synced key file","If the key legitimately lives elsewhere, run the store without requiring sync/validation of this field"],"exampleFix":"// before\nvar identity = new SyncedIdentityStore(\n    new KeyFileStrategy(FilePath.of(\"~/.ssh/id_rsa\")), null, null);\n// after\nvar syncedKey = FilePath.of(DataStorage.get().installPath(true))\n    .join(\"id_rsa\"); // copy key file here first\nvar identity = new SyncedIdentityStore(\n    new KeyFileStrategy(syncedKey), null, null);","handlingStrategy":"validation","validationCode":"if (identity.getSshIdentity() instanceof KeyFileStrategy f\n        && !f.getFile().isInDataDirectory()) {\n    // fix or copy the key into the data directory before checkComplete()\n}","typeGuard":"boolean isSynced(SecretRetrievalStrategy s) {\n    return !(s instanceof KeyFileStrategy f) || f.getFile().isInDataDirectory();\n}","tryCatchPattern":"try { store.checkComplete(); }\ncatch (ValidationException e) {\n    if (\"Key file is not synced\".equals(e.getMessage())) { /* prompt key import */ }\n}","preventionTips":["Always import key files through XPipe's UI so they are copied into the data directory","Never point identity stores at raw ~/.ssh paths when sync is required"],"tags":["validation","ssh","file-sync","identity-store"],"backgroundTag":"invalid-config-value","analyzedSha":"d85ca821baa46092a320ebb13546d7240adb74f8","analyzedAt":"2026-09-06T14:30:08.251Z","contentChangedAt":"2026-09-06T14:30:08.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}