Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong line numbers in stacktraces in dev mode on console, in IntelliJ/WebStorm and VSCode #10138

Closed
dmoebius opened this issue Jun 11, 2023 · 12 comments · Fixed by #10769
Closed

Comments

@dmoebius
Copy link

dmoebius commented Jun 11, 2023

Describe the bug

In Dev mode, SvelteKit modifies the line numbers of server stacktraces by calling fix_stack_trace(), which in turn calls vite.ssrRewriteStacktrace(stack). This is done by wrapping the Error object in a Proxy (method handle_error_and_jsonify() in kit/src/runtime/server/utils.js). This works in some environments, e.g. StackBlitz, but not on the console or IntelliJ/WebStore or VSCode.

Reproduction

  1. Create a new SvelteKit demo app with Typescript:
npm create svelte@latest my-app
cd my-app
npm install
  1. Add one file src/routes/+page.server.ts with the following content:
export const load = (({}) => {
    throw new Error("boo")
})
  1. Start app in dev mode with npm run dev on the console and open http://localhost:5173/

You'll get the following stacktrace:

Error: boo
    at load (/home/dmoebius/src/tmp/my-app/src/routes/+page.server.ts:4:9)
    at Module.load_server_data (/home/dmoebius/src/tmp/my-app/node_modules/@sveltejs/kit/src/runtime/server/page/load_data.js:57:41)
    at eval (/home/dmoebius/src/tmp/my-app/node_modules/@sveltejs/kit/src/runtime/server/page/index.js:150:41)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

Notice that the line numbers are wrong:

  • Wrong: +page.server.ts:4:9
    Correct: +page.server.ts:2:9
  • Wrong: @sveltejs/kit/src/runtime/server/page/load_data.js:57:41
    Correct: load_data.js:51:41 (as of @sveltejs/kit 1.20.2)
  • Wrong: @sveltejs/kit/src/runtime/server/page/index.js:150:41
    Correct: index.js:141:19 (as of @sveltejs/kit 1.20.2)

Notice that the line numbers are not just off by a fixed offset.

The same happens if you use the IDEs IntelliJ/Webstorm or VSCode to execute rpm run dev.

Logs

No response

System Info

System:
    OS: Linux 6.3 Arch Linux
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 14.27 GB / 30.99 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 20.2.0 - /usr/bin/node
    Yarn: 1.22.19 - /usr/bin/yarn
    npm: 8.19.2 - /usr/bin/npm
  Browsers:
    Firefox: 114.0
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.1.0 
    @sveltejs/kit: ^1.5.0 => 1.20.2 
    svelte: ^3.54.0 => 3.59.1 
    vite: ^4.3.0 => 4.3.9

Severity

annoyance

Additional Information

The culprit is in https://github.com/sveltejs/kit/blob/master/packages/kit/src/runtime/server/utils.js#L98 line 98ff:

export async function handle_error_and_jsonify(event, options, error) {
	if (error instanceof HttpError) {
		return error.body;
	} else {
		if (__SVELTEKIT_DEV__ && typeof error == 'object') {
			error = new Proxy(error, {
				get: (target, property) => {
					if (property === 'stack') {
						return fix_stack_trace(target.stack);
					}

					return Reflect.get(target, property, target);
				}
			});
		}

This wraps the error in a Proxy that fixes the stacktrace when the stack property is accessed. Problem: when running on the console or in IDEs such as IntelliJ or VSCode, then those environments never access error.stack directly to print the stacktrace! I don't know which mechanism they use to output it, but I debugged it and although the proxy gets created, the proxy get method never gets called. It is indeed called in e.g. StackBlitz, because when you try to do the same there, you'll get correct stacktraces, e.g.: https://stackblitz.com/edit/sveltejs-kit-template-default-htvqfu?file=src%2Froutes%2F%2Bpage.server.ts

The regression has been introduced by this commit on Jan 13.

Btw, fix_stack_trace() in turn calls vite.ssrRewriteStacktrace(stack) in kit/src/exports/vite/dev/index.js:

	/** @param {string} stack */
	function fix_stack_trace(stack) {
		return stack ? vite.ssrRewriteStacktrace(stack) : stack;
	}

AFAICT Vite's ssrRewriteStacktrace(stack) is no longer the right way to fix an ssr stacktrace. It has been obsoleted by ssrFixStacktrace(error) (see vitejs/vite#7045), which should be used instead, because it takes care that the line numbers don't get mangled if you accidentally call the method twice; they memoize if it has been called already.

Prior work

I checked very thoroughly for previous issues about this issue. It is not related to:

@dmoebius
Copy link
Author

The issue could be fixed by changing handle_error_and_jsonify to:

export async function handle_error_and_jsonify(event, options, error) {
	if (error instanceof HttpError) {
		return error.body;
	} else {
		if (__SVELTEKIT_DEV__ && typeof error == 'object') {
			fix_stack_trace(error);
		}
                ...

and then changing fix_stack_trace() in /kit/src/exports/vite/dev/index.js to:

	function fix_stack_trace(error) {
		error && vite.ssrFixStacktrace(error);
 	}

There's no need for a Proxy object. Note that vite.ssrFixStacktrace(error) changes error in-place.

If I find the time I'd might prepare a PR.

@NfNitLoop
Copy link

I'm running into this as well.

As I'm converting a project from purely client-side Svelte to SvelteKit, there are lots of references to browser-only objects like window that are causing errors during SSR. It's a bit of a pain to track them all down when the stack traces are sending me to lines that don't have window on them! (I can't just do a global search/replace, because some of the code does only run after, say, onMount(). I need to find references that are getting used in SSR. Working stack traces would be a big help!)

@benquan
Copy link

benquan commented Sep 4, 2023

Why is this problem not a bigger issue? I've notiiced the problem for quite a while and it takes a lot of time figuring out what is wrong when something fails. I tried to reproduce and as @dmoebius shows, It does not take much to replicate it. On long files its even harder to find the problem.

@Joonel
Copy link

Joonel commented Sep 12, 2023

So in order to fix that and to know on which line I have an error (such a basic programming feature), I have to download entire SvelteKit sources, make these edits and then recompile the thing? I just use SvelteKit as npm package, how would I will do all this high level stuff...

@dmoebius
Copy link
Author

dmoebius commented Sep 14, 2023

You could use patch-package to patch this changes during npm install or after git checkout. That's what I do. (I don't have the time to fork and build SvelteKit either.)

@dmoebius
Copy link
Author

dmoebius commented Sep 14, 2023

Btw. FYI: This whole issue was created for SvelteKit 1.20.x, Svelte 3.x (!), Vite 4.3.x. I didn't have the time to check whether this issue occurs with the newest versions. Might be worth a try.

@Joonel
Copy link

Joonel commented Sep 14, 2023

Latest Vite, Svelte (4.x) and SvelteKit set share the same issue.

@dmoebius
Copy link
Author

dmoebius commented Sep 14, 2023

You could use patch-package to patch this changes during npm install or after git checkout. That's what I do. (I don't have the time to fork and build SvelteKit either.)

Here's the patch file, for sveltekit v1.20.1 at least. Maybe it works for newer versions, too.
@sveltejs+kit+1.20.1.zip

(PS: for some reason GitHub doesn't let me attach the *.patch file directly; I had to zip it first. 🤷 )

Unzip it, put it into your workspace patches/ folder and use patch-package.

@benquan
Copy link

benquan commented Sep 15, 2023

I recreated the patch for the latest sveletkit (v1.25.0). It works better on a simplified error like above, but on a more complex project it was still off by some lines.

@vialcollet
Copy link

Hi all
This is really time consuming to deal with this issue. Any idea when this can be fixed?

@eltigerchino
Copy link
Member

eltigerchino commented Sep 22, 2023

This wraps the error in a Proxy that fixes the stacktrace when the stack property is accessed. Problem: when running on the console or in IDEs such as IntelliJ or VSCode, then those environments never access error.stack directly to print the stacktrace! I don't know which mechanism they use to output it, but I debugged it and although the proxy gets created, the proxy get method never gets called.

This is it. I've tested on Node 16, 18, 20 and the result is still the same. console.log(error) completely bypasses the proxy while console.log(error.stack) correctly uses the proxy.

AFAICT Vite's ssrRewriteStacktrace(stack) is no longer the right way to fix an ssr stacktrace. It has been obsoleted by ssrFixStacktrace(error) (see vitejs/vite#7045), which should be used instead, because it takes care that the line numbers don't get mangled if you accidentally call the method twice; they memoize if it has been called already.

Exactly right. We can safely use ssrFixStacktrace now. https://github.com/vitejs/vite/blob/aae3a83b5fb49bbd9f174cfeac66f00483829da4/packages/vite/src/node/ssr/ssrStacktrace.ts#L87-L98

Sorry this flew under the radar. Thank you to the great work by the issue author.

I recreated the patch for the latest sveletkit (v1.25.0). It works better on a simplified error like above, but on a more complex project it was still off by some lines.

@benquan can you help provide a reproducible for this? I'm not sure how to diagnose this (and it might then be an issue with vite's ssrFixStacktrace).

@eltigerchino
Copy link
Member

eltigerchino commented Sep 22, 2023

The fix in #10138 (comment) only fixed some server stack traces, but I think errors occurring during module importing have the wrong line numbers as well.

You can see the wrong line numbers in the server console and the vite HMR overlay in the browser.

// _bad.js
const bad = foo().toUpperCase();
export default bad;

function foo() {}
<script>
    // +page.svelte
	import bad from './_bad.js';
</script>

<h1>{bad}</h1>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants