Skip to content

fix: preserve error info from streamed_fetch parse failure#1434

Open
OnlookerRs wants to merge 1 commit into
kwaroran:mainfrom
OnlookerRs:fix/native-fetch-error-info-loss
Open

fix: preserve error info from streamed_fetch parse failure#1434
OnlookerRs wants to merge 1 commit into
kwaroran:mainfrom
OnlookerRs:fix/native-fetch-error-info-loss

Conversation

@OnlookerRs
Copy link
Copy Markdown
Contributor

PR Checklist

  • Required Checks
    • Have you added type definitions?
    • Have you tested your changes?
    • Have you checked that it won't break any existing features?
  • If your PR uses models1, check the following:
    • Have you checked if it works normally in all models?
    • Have you checked if it works normally in all web, local, and node-hosted versions? If it doesn't, have you blocked it in those versions?
  • If your PR is highly AI generated2, check the following:
    • Have you understood what the code does?
    • Have you cleaned up any unnecessary or redundant code?
    • Is it not a huge change?

Summary

In fetchNative()'s Tauri streamed_fetch path (globalApi.svelte.ts), the catch block around JSON.parse(res) stores JSON.stringify(e) as the error message. Because Error instances have non-enumerable message / name / stack properties, JSON.stringify(errorObj) always evaluates to "{}". The downstream throw new Error(error) then produces an Error whose message is literally the string "{}", and every caller (custom providers, plugins) only sees Error: {} with no diagnostic value, making bug reports unactionable.

Related Issues

None.

Changes

  • Replaced error = JSON.stringify(e) in the streamed_fetch parse-failure catch with e.message || e.name || 'streamed_fetch parse failed'
  • Added an instanceof Error guard so non-Error throws still get a sensible string via String(e)
  • Inline comment documents the non-enumerable-properties quirk so the next reader doesn't reintroduce the regression

Impact

  • Plugin / custom provider error toasts now surface the actual cause (e.g. Unexpected end of JSON input) instead of Error: {}
  • Behavior on the success path is unchanged — the catch is the only modified branch
  • Return shape is identical (error remains a string), so the subsequent if (error !== '') throw new Error(error) flow is fully backwards compatible
  • No public API change

Additional Notes

The exact Rust-side condition that produces the malformed/non-JSON response from invoke('streamed_fetch') is hard to reproduce on demand, but the JS-side bug pattern is trivially verifiable in any runtime:

JSON.stringify(new Error('hi')) // → "{}"

A real user hit this via a custom plugin's error handler — their toast read 캐시 오류 - 요청 취소됨: {}, with the stack pointing at this exact catch via OB (minified fetchNative). With the fix, the same path will now show the underlying cause.

Footnotes

  1. Modifies the behavior of prompting, requesting, or handling responses from AI models.

  2. Over 80% of the code is AI generated.

JSON.stringify(error) returns "{}" for Error objects because their
message/name/stack properties are non-enumerable. The previous catch
in fetchNative discarded the real cause:

    } catch (e) {
        error = JSON.stringify(e)   // → always "{}"
    }

Downstream callers (custom providers, plugins) then saw `Error: {}`
with no diagnostic value, making bug reports unactionable.

Replace with `e.message || e.name || fallback` to surface the actual
cause (e.g. "Unexpected end of JSON input") in the thrown Error.
Copy link
Copy Markdown
Collaborator

@cubicj cubicj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the failure path. JSON.stringify(new Error(...)) drops the message to {}, so this preserves useful parse error details without changing the success path or return shape.

Check, tests, and build pass locally.

Approving — thanks for the contribution!

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.

2 participants