Skip to content

Commit 6cc8f37

Browse files
dyoung522claude
andcommitted
fix: show concise JSON parsing errors without stack trace
When syncing mods or tools, invalid JSON (e.g., unescaped backslashes in Windows paths) would display a full stack trace, making it appear as if the program crashed. The error was actually being caught, but using e.full_message included the entire backtrace. Changes: - Use e.message instead of e.full_message in mods.rb and tools.rb - Add comprehensive tests for JSON parsing error handling - Verify errors are displayed concisely without stack traces - Verify sync continues processing valid URLs after encountering errors Before: Skipped; Invalid JSON: /path/to/gems/.../json.rb:353:in 'parse': ... [60+ lines of stack trace] After: Skipped; Invalid JSON: invalid escape character in string: '\Users\...' Testing: - All 301 tests passing - Added 4 new tests for JSON error handling Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 43cb6d1 commit 6cc8f37

6 files changed

Lines changed: 75 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file.
1717
- Track and report both fetch failures and delete failures with detailed summaries
1818
- Enhanced dry-run output showing all entities that would be deleted
1919
- Add Firestore cache invalidation for mod/tool deletions
20+
- Fix JSON parsing error messages during sync to show concise error instead of full stack trace
2021

2122
### v2.3.0 - 2025-12-18
2223

error

Whitespace-only changes.

lib/icarus/mod/tools/sync/mods.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def info_array
2626
warn "Skipped; Failed to retrieve #{url}"
2727
next
2828
rescue JSON::ParserError => e
29-
warn "Skipped; Invalid JSON: #{e.full_message}"
29+
warn "Skipped; Invalid JSON: #{e.message}"
3030
next
3131
end.flatten.compact
3232
end

lib/icarus/mod/tools/sync/tools.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def info_array
2828
warn "Skipped; Failed to retrieve #{url}"
2929
next
3030
rescue JSON::ParserError => e
31-
warn "Skipped; Invalid JSON: #{e.full_message}"
31+
warn "Skipped; Invalid JSON: #{e.message}"
3232
next
3333
end.flatten.compact
3434
end

spec/icarus/mod/tools/sync/mods_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,42 @@
3030
it "returns an array of Modinfo objects" do
3131
expect(modsync.info_array).to all(be_a(Icarus::Mod::Tools::Modinfo))
3232
end
33+
34+
context "when JSON parsing fails" do
35+
let(:valid_url) { "https://example.com/valid.json" }
36+
let(:invalid_url) { "https://example.com/invalid.json" }
37+
let(:valid_response) { { mods: [{ name: "Valid Mod", author: "Author", description: "Test" }] } }
38+
39+
before do
40+
modsync.instance_variable_set(:@info_array, nil)
41+
allow(firestore_double).to receive(:modinfo).and_return([valid_url, invalid_url])
42+
allow_any_instance_of(Icarus::Mod::Tools::Sync::Helpers).to receive(:retrieve_from_url).with(valid_url).and_return(valid_response)
43+
allow_any_instance_of(Icarus::Mod::Tools::Sync::Helpers).to receive(:retrieve_from_url).with(invalid_url).and_raise(
44+
JSON::ParserError.new("invalid escape character in string: '\\Users\\foo\\bar' at line 1 column 10")
45+
)
46+
end
47+
48+
it "warns with a concise error message without stack trace" do
49+
stderr_output = StringIO.new
50+
original_stderr = $stderr
51+
$stderr = stderr_output
52+
53+
modsync.info_array
54+
55+
$stderr = original_stderr
56+
output = stderr_output.string
57+
58+
expect(output).to match(/Skipped; Invalid JSON: invalid escape character/)
59+
expect(output).not_to match(/JSON::Ext::Parser/)
60+
expect(output).not_to match(/lib\/ruby\/gems/)
61+
end
62+
63+
it "skips the invalid URL and continues processing" do
64+
result = modsync.info_array
65+
expect(result.length).to eq(1)
66+
expect(result.first.name).to eq("Valid Mod")
67+
end
68+
end
3369
end
3470

3571
describe "#find" do

spec/icarus/mod/tools/sync/tools_spec.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,42 @@
3030
it "returns an array of Toolinfo objects" do
3131
expect(toolsync.info_array).to all(be_a(Icarus::Mod::Tools::Toolinfo))
3232
end
33+
34+
context "when JSON parsing fails" do
35+
let(:valid_url) { "https://example.com/valid.json" }
36+
let(:invalid_url) { "https://example.com/invalid.json" }
37+
let(:valid_response) { { tools: [{ name: "Valid Tool", author: "Author", description: "Test", fileType: "EXE", fileURL: "http://example.com/tool.exe" }] } }
38+
39+
before do
40+
toolsync.instance_variable_set(:@info_array, nil)
41+
allow(firestore_double).to receive(:toolinfo).and_return([valid_url, invalid_url])
42+
allow_any_instance_of(Icarus::Mod::Tools::Sync::Helpers).to receive(:retrieve_from_url).with(valid_url).and_return(valid_response)
43+
allow_any_instance_of(Icarus::Mod::Tools::Sync::Helpers).to receive(:retrieve_from_url).with(invalid_url).and_raise(
44+
JSON::ParserError.new("invalid escape character in string: '\\Users\\foo\\bar' at line 1 column 10")
45+
)
46+
end
47+
48+
it "warns with a concise error message without stack trace" do
49+
stderr_output = StringIO.new
50+
original_stderr = $stderr
51+
$stderr = stderr_output
52+
53+
toolsync.info_array
54+
55+
$stderr = original_stderr
56+
output = stderr_output.string
57+
58+
expect(output).to match(/Skipped; Invalid JSON: invalid escape character/)
59+
expect(output).not_to match(/JSON::Ext::Parser/)
60+
expect(output).not_to match(/lib\/ruby\/gems/)
61+
end
62+
63+
it "skips the invalid URL and continues processing" do
64+
result = toolsync.info_array
65+
expect(result.length).to eq(1)
66+
expect(result.first.name).to eq("Valid Tool")
67+
end
68+
end
3369
end
3470

3571
describe "#find" do

0 commit comments

Comments
 (0)