diff --git a/plugins/sync/frontend/src/SyncSettings.svelte b/plugins/sync/frontend/src/SyncSettings.svelte
index c8df788..0c72417 100644
--- a/plugins/sync/frontend/src/SyncSettings.svelte
+++ b/plugins/sync/frontend/src/SyncSettings.svelte
@@ -193,6 +193,11 @@
{#if resultMsg && !errorMsg}
{resultMsg}
{/if}
+ {#if settings && settings.lastError && !errorMsg}
+
+ Last sync error: {sanitizeError(settings.lastError)}
+
+ {/if}
Server
diff --git a/scripts/check.sh b/scripts/check.sh
index d6081b9..ca03daf 100755
--- a/scripts/check.sh
+++ b/scripts/check.sh
@@ -223,6 +223,8 @@ if command -v node &>/dev/null; then
report "browser inbox frontend behavior" $?
node "$ROOT/scripts/smoke-search-plugin.js"
report "search frontend behavior" $?
+ node "$ROOT/scripts/smoke-sync-plugin.js"
+ report "sync frontend behavior" $?
else
echo " ⚠️ node not available — skipping frontend smoke"
fi
diff --git a/scripts/smoke-sync-plugin.js b/scripts/smoke-sync-plugin.js
new file mode 100644
index 0000000..543dfb5
--- /dev/null
+++ b/scripts/smoke-sync-plugin.js
@@ -0,0 +1,19 @@
+#!/usr/bin/env node
+const fs = require('fs');
+const path = require('path');
+
+const root = path.resolve(__dirname, '..');
+const sourcePath = path.join(root, 'plugins', 'sync', 'frontend', 'src', 'SyncSettings.svelte');
+const source = fs.readFileSync(sourcePath, 'utf8');
+
+if (!source.includes('settings.lastError')) {
+ throw new Error('SyncSettings must render persisted settings.lastError');
+}
+if (!source.includes('sanitizeError(settings.lastError)')) {
+ throw new Error('SyncSettings must sanitize persisted sync errors before rendering');
+}
+if (!source.includes('Last sync error')) {
+ throw new Error('SyncSettings must label the persisted sync error');
+}
+
+console.log('sync plugin smoke passed');