Skip to content

fix(reporter): PasteBin upload - timeout, missing Jackson dep, silent failures - #70

Open
soloturn wants to merge 6 commits into
masterfrom
soloturn-pastebin-upload-fixes
Open

fix(reporter): PasteBin upload - timeout, missing Jackson dep, silent failures#70
soloturn wants to merge 6 commits into
masterfrom
soloturn-pastebin-upload-fixes

Conversation

@soloturn

Copy link
Copy Markdown
Contributor

AI-assisted change proposal. Filed by agent driven by @soloturn via GDD.

Combines #64 and #65 - both PasteBin-upload fixes found while manually testing the reporter dialog, closing both in favor of this one.

Summary

1. Upload hung forever with no feedback

PastebinUploadRunnable makes a real HTTP call with no timeout of its own. upload() now submits to a daemon-thread executor and waits up to 30s (awaitUpload(), a plain Swing-free method so the timeout/exception-unwrapping logic is directly testable) before treating it as failed, instead of leaving the button disabled and the status label reading "please wait" forever with no way to tell "still working" from "will never finish".

2. NoClassDefFoundError: com/fasterxml/jackson/core/type/TypeReference

Reproduced directly by calling PastebinUploadRunnable.call() outside the dialog. jpastebin's own embedded META-INF/maven/org/jpastebin/pom.xml (inside the jar) pins jackson-databind/jackson-core/jackson-annotations 2.9.7, but the POM Gradle actually resolves for org:jpastebin:1.0.1 from the JBoss repo is an empty Nexus-generated stub with no <dependencies> at all - so Gradle never pulled Jackson in, and it only ever surfaced the moment someone clicked the button.

Declared all three explicitly via the jackson-bom platform rather than three separately-pinned versions: jackson-annotations renumbered its own versioning away from core/databind's x.y.z scheme starting at 2.20, so hand-pinning all three to the same version string breaks depending which release line you pick. 2.9.7 is a 2018 release with known CVEs; Jackson's 2.x line keeps this level of API stable, so the current release is a safe drop-in.

3. Upload failures only ever showed a JOptionPane, with no trace anywhere else

Which is exactly what made bug #2 hard to pin down in the first place - the exception only ever appeared as a popup, gone the moment it's dismissed, with nothing printed anywhere for whoever launched the process (a script, a supervisor, a developer tailing output) to find afterward. uploadFailed() now unconditionally prints the exception to stderr before showing the dialog - the same fix applied to the timeout case above, since both funnel through the same failure path.

Test plan

  • New UploadPanelTest - drives the timeout path directly via the injectable timeout constructor and awaitUpload().
  • New UploadPanelFailureLoggingTest - drives a forced upload failure via a package-private test hook and asserts the exception lands on stderr.
  • Reproduced the Jackson error directly against the real API before the fix, confirmed a successful real upload after.
  • ./gradlew build - clean.

Related

soloturn and others added 5 commits August 22, 2026 13:00
Found while manually testing the reporter dialog: clicking "PasteBin"
disabled the button, showed "please wait", and never resolved either
way. PastebinUploadRunnable.call() makes a real HTTP POST via jpastebin
with no timeout of its own, and UploadPanel.upload() just ran it on a
bare thread and waited unboundedly for callable.call() to return - a
slow or unreachable server left no way to tell "still working" from
"will never finish".

upload() now submits to an ExecutorService and waits at most 30s
(configurable via a package-private constructor for tests) via
future.get(timeout, SECONDS), cancelling the future and reporting a
clear "Upload timed out after 30s" failure if it's not done by then.

The wait-and-dispatch logic is split into a small static method,
awaitUpload(), that's plain Future/Consumer plumbing with no Swing
dependency - lets UploadPanelTest exercise the timeout, success, and
underlying-failure-unwrapped-from-ExecutionException paths directly
against real Futures, without a button-click harness.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Clicking "PasteBin" threw NoClassDefFoundError:
com/fasterxml/jackson/core/type/TypeReference the first time it
actually reached a Jackson class - reproduced directly by calling
PastebinUploadRunnable.call() outside the dialog.

jpastebin's own embedded META-INF/maven/org/jpastebin/pom.xml (inside
the jar) pins jackson-databind/jackson-core/jackson-annotations
2.9.7, but the POM Gradle actually resolves for org:jpastebin:1.0.1
from the JBoss repo is an empty Nexus-generated stub with no
<dependencies> at all - so Gradle never pulled Jackson in.

Declares all three explicitly via the jackson-bom platform rather
than three separately-pinned versions: jackson-annotations renumbered
its own versioning away from core/databind's x.y.z scheme starting at
2.20, so hand-pinning all three to the same string breaks depending on
which release line you pick. The BOM keeps them resolvable together
regardless. 2.9.7 is a 2018 release with known CVEs; Jackson's 2.x
line keeps this level of API (ObjectMapper, TypeReference,
annotations) stable, so the current release is a safe drop-in rather
than matching jpastebin's old pin.

Verified end to end: a direct call to PastebinUploadRunnable now
succeeds against the real API instead of throwing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
uploadFailed() only ever showed a JOptionPane - nothing else in this
codebase logs upload failures anywhere. That popup reaches whoever
happens to be watching the screen at that exact moment and leaves no
trace at all once dismissed; whoever launched the process (a script,
a supervisor, a developer tailing output) has no way to find out what
happened after the fact. This is exactly what made the Jackson
NoClassDefFoundError above hard to pin down in the first place - it
only ever appeared as a popup.

e.printStackTrace(System.err) now runs unconditionally before the
dialog, on the same thread, so it can't get lost even if the
JOptionPane is dismissed instantly. New package-private
uploadForTesting() hook (bypasses the real ActionListener/network
call so UploadPanelFailureLoggingTest can drive a failure directly)
plus the same GlobalProperties NPE guard used elsewhere in this repo
(needed just to construct GlobalProperties() in cr-core's own test
classpath - see the sibling PRs).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…es' into soloturn-pastebin-upload-fixes

# Conflicts:
#	cr-core/src/main/java/org/terasology/crashreporter/pages/UploadPanel.java
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 21d2efac-7cb7-44a2-a2b0-8c603a95bb72


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@soloturn

Copy link
Copy Markdown
Contributor Author

Re: @BenjaminAmos's comment on #64 (now here) about tests reaching out to external URLs - clarifying, since that PR's gone: neither UploadPanelTest nor UploadPanelFailureLoggingTest ever touches the network.

  • new URL("https://pastebin.com/...") only parses a URL string - it never opens a connection (that only happens on openConnection()/openStream(), which these tests never call).
  • Every simulated upload is a hand-written Callable<URL> (sleep-then-return, return-immediately, or throw) passed straight to UploadPanel.awaitUpload()/uploadForTesting(). PastebinUploadRunnable - the class that actually makes the real HTTP POST - is never instantiated by any test here.

So these are already fully offline and deterministic; nothing to change on that front. Happy to add an explicit comment in the test file noting this if it'd help future reviewers.

Addresses @BenjaminAmos's review concern on #64 (now folded into this
PR): these tests are already fully offline - PastebinUploadRunnable is
never instantiated, and new URL(...) only parses a string, it never
opens a connection. Making that explicit in the class javadoc so it
isn't mistaken for a real network-touching test again.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant