benweet/stackedit · critical · Error
Synchronization failed due to token inconsistency.
Error message
Synchronization failed due to token inconsistency.
What it means
During synchronization the app keeps a localSettings.syncSub identifying which account sub owns the sync data. If a sync token's sub differs from the previously stored syncSub, syncSvc throws 'Synchronization failed due to token inconsistency.' to stop one account from writing into another account's synced data.
Source
Thrown at src/services/syncSvc.js:631
};
/**
* Sync the whole workspace with the main provider and the current file explicit locations.
*/
const syncWorkspace = async (skipContents = false) => {
try {
const workspace = store.getters['workspace/currentWorkspace'];
const syncContext = new SyncContext();
// Store the sub in the DB since it's not safely stored in the token
const syncToken = store.getters['workspace/syncToken'];
const localSettings = store.getters['data/localSettings'];
if (!localSettings.syncSub) {
store.dispatch('data/patchLocalSettings', {
syncSub: syncToken.sub,
});
} else if (localSettings.syncSub !== syncToken.sub) {
throw new Error('Synchronization failed due to token inconsistency.');
}
const changes = await workspaceProvider.getChanges();
// Apply changes
applyChanges(workspaceProvider.prepareChanges(changes));
workspaceProvider.onChangesApplied();
// Prevent from sending items too long after changes have been retrieved
const ifNotTooLate = tooLateChecker(restartSyncAfter);
// Find and save one item to save
await utils.awaitSome(() => ifNotTooLate(async () => {
const storeItemMap = {
...store.state.file.itemsById,
...store.state.folder.itemsById,
...store.state.syncLocation.itemsById,
...store.state.publishLocation.itemsById,View on GitHub (pinned to 6dce2a5e36)
Solutions
- Reconnect the sync location with the account whose sub matches localSettings.syncSub.
- Clear/patch localSettings.syncSub (or reset local settings) so the next sync binds to the current account, accepting that the data owner changes.
- Verify which account the workspace data actually belongs to before overriding syncSub to avoid cross-account contamination.
- If the account was permanently switched, migrate/export the workspace data and start a fresh sync location.
Example fix
// before
await store.dispatch('data/patchLocalSettings', { syncSub: syncToken.sub }); // silently skipped when stale
await sync();
// after
const localSettings = store.getters['data/localSettings'];
if (localSettings.syncSub && localSettings.syncSub !== syncToken.sub) {
await store.dispatch('data/patchLocalSettings', { syncSub: syncToken.sub }); // deliberate owner switch
}
await sync(); Defensive patterns
Strategy: validation
Validate before calling
const localSettings = store.getters['data/localSettings'];
const syncTokenSub = syncToken && syncToken.sub;
if (localSettings.syncSub && syncTokenSub && localSettings.syncSub !== syncTokenSub) {
// resolve deliberately before syncing:
// reconnect with the original account, or confirm a switch and patch syncSub
} Type guard
function isSyncSubConsistent(localSettings, syncToken) {
return Boolean(syncToken && syncToken.sub && (!localSettings.syncSub || localSettings.syncSub === syncToken.sub));
} Try / catch
try {
await syncSvc.sync();
} catch (err) {
if (err.message.includes('token inconsistency')) {
// surface an account-switch dialog instead of auto-overwriting syncSub
} else throw err;
} Prevention
- Always check localSettings.syncSub against the current token before starting sync
- Make account switches an explicit user action that updates syncSub intentionally
- Back up workspace data before overriding syncSub to a new owner
- Avoid sharing app profiles between accounts on the same machine
When it happens
Trigger: Running sync (syncSvc) when the current workspace provider's sync token belongs to a different account than localSettings.syncSub — e.g. switching main/secondary accounts, restoring data from another account, or a stale localSettings entry after an account change.
Common situations: Reconnecting the sync location with a different Google/GitLab account; importing a workspace export from another user; localSettings surviving an account switch and pointing at the old sub; team setup where two users share a machine profile.
Related errors
- Dropbox account ID not expected.
- GitHub account ID not expected.
- GitLab account ID not expected.
- Google account ID not expected.
- WordPress account ID not expected.
AI-assisted analysis of benweet/stackedit@6dce2a5e36 (2026-09-01).
Data as JSON: /api/errors/3c509eed78bdda6e.
Report an issue: GitHub.