Skip to content

Commit 40e50d9

Browse files
fix: don't crash uninstall on malformed settings.json (#481)
If settings.json contained invalid JSON, JSON.parse threw a SyntaxError, which has no .code, so the catch rethrew it and crashed the script — after the mode flag and config file were already removed, leaving cleanup half-done. Handle SyntaxError explicitly: warn that the statusLine entry couldn't be removed and leave the file untouched, since invalid JSON can't be safely edited. Adds a regression test that a malformed settings.json exits 0, warns, and is left byte-for-byte intact. Closes #434 Co-authored-by: isaukywhite <50426537+isaukywhite@users.noreply.github.com>
1 parent b8f20b8 commit 40e50d9

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

scripts/uninstall.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,12 @@ try {
4848
}
4949
}
5050
} catch (e) {
51-
if (e.code !== 'ENOENT') throw e;
51+
if (e.code === 'ENOENT') {
52+
// no settings.json — nothing to clean
53+
} else if (e instanceof SyntaxError) {
54+
// ponytail: malformed settings.json — can't safely edit it; leave intact, warn
55+
console.warn(`settings.json is malformed — could not remove the ponytail statusLine entry. Remove it manually from: ${settingsPath} (${e.message})`);
56+
} else {
57+
throw e;
58+
}
5259
}

tests/uninstall.test.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,28 @@ assert.equal(
8484
'a combined statusLine must be left untouched, not partially destroyed',
8585
);
8686

87+
// #434: a malformed settings.json must not crash the script mid-cleanup. It
88+
// can't be safely edited, so uninstall warns and leaves the file byte-for-byte
89+
// intact instead of throwing a SyntaxError after other state was already removed.
90+
const malformedSettings = '{ "statusLine": { "command": "ponytail-statusline.sh", broken';
91+
fs.writeFileSync(settingsPath, malformedSettings);
92+
93+
result = runUninstall(env);
94+
assert.equal(
95+
result.status,
96+
0,
97+
`expected exit 0 on malformed settings.json, got:\n${result.stdout}${result.stderr}`,
98+
);
99+
assert.ok(
100+
/malformed/i.test(result.stdout + result.stderr),
101+
'must warn that the statusLine entry could not be removed',
102+
);
103+
assert.equal(
104+
fs.readFileSync(settingsPath, 'utf8'),
105+
malformedSettings,
106+
'malformed settings.json must be left unchanged',
107+
);
108+
87109
// Running on an already-clean machine must not throw.
88110
result = runUninstall({ HOME: path.join(temp, 'home-empty'), USERPROFILE: path.join(temp, 'home-empty') });
89111
assert.equal(result.status, 0, result.stderr);

0 commit comments

Comments
 (0)