sveltejs / language-tools

The Svelte Language Server, and official extensions which use it
MIT License
1.25k stars 199 forks source link

Extension keep crashing: MarkCompactCollector #2510

Closed Extarys closed 1 month ago

Extarys commented 1 month ago

Describe the bug

Every time I try to run "Format document", after 10-20 seconds I get an error in Output > Svelte and nothing happens


<--- Last few GCs --->

[1079:0x63000364000]    76965 ms: Scavenge 3914.9 (4084.8) -> 3912.1 (4087.0) MB, pooled: 0 MB, 4.13 / 0.00 ms  (average mu = 0.814, current mu = 0.575) allocation failure; 
[1079:0x63000364000]    76986 ms: Scavenge 3917.1 (4087.0) -> 3914.2 (4089.5) MB, pooled: 0 MB, 7.72 / 0.00 ms  (average mu = 0.814, current mu = 0.575) allocation failure; 

<--- JS stacktrace --->

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

[Error - 20:51:07] Server process exited with signal SIGABRT.
[Info  - 20:51:07] Connection to server got closed. Server will restart.
true
Initialize language server at  file:///srv/repo
Initialize new ts service at  /srv/repo/apps/ui/tsconfig.json
Trying to load configs for /srv/repo/apps/ui
Loaded config at  /srv/repo/apps/ui/svelte.config.js
SnapshotManager File Statistics:
Project files: 295
Svelte files: 212
From node_modules: 0
Total: 295
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback

(I have a lot of those)

Output > Extension Host

2024-09-20 21:15:10.088 [error] Error: Pending response rejected since connection got disposed
    at Object.dispose (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/common/connection.js:1167:27)
    at Object.dispose (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-languageclient/lib/common/client.js:1586:35)
    at LanguageClient.handleConnectionClosed (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-languageclient/lib/common/client.js:1155:34)
    at LanguageClient.handleConnectionClosed (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-languageclient/lib/node/main.js:180:22)
    at closeHandler (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-languageclient/lib/common/client.js:1142:18)
    at CallbackList.invoke (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
    at Emitter.fire (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
    at closeHandler (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/common/connection.js:314:26)
    at CallbackList.invoke (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
    at Emitter.fire (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
    at IPCMessageReader.fireClose (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/common/messageReader.js:41:27)
    at ChildProcess.<anonymous> (/home/user/.var/app/com.vscodium.codium/data/codium/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/vscode-jsonrpc/lib/node/main.js:37:45)
    at ChildProcess.emit (node:events:531:35)
    at maybeClose (node:internal/child_process:1105:16)
    at Socket.<anonymous> (node:internal/child_process:457:11)
    at Socket.emit (node:events:519:28)
    at Pipe.<anonymous> (node:net:338:12)

Reproduction

I have this issue with VSCodium rpm and VSCodium flatpak. No idea how to reproduce.

Monorepo with a ui folder, containing svelte.config.js (Sveltekit, vite).

Formatting work on a 25 LOC file, but another component with 95 LOC make it crash every single time. I tried multiple page and they mostly all make the language server crash.

I don't really know what you need, please let me know. It was working fine 2 days ago, I didn't update any npm package, but I have no idea if vscode did update extensions in the background, so I erased all tmp and config files and tested with flatpak too, issue still persist.

Expected behaviour

The extension shouldn't crash; The document should get formatted

System Info

Which package is the issue about?

Svelte for VS Code extension, svelte-language-server

Additional Information, eg. Screenshots

Old similar issue: https://github.com/jamesbirtles/svelte-vscode/issues/26

jasonlyu123 commented 1 month ago

We'll definitely need a reproduction to help you. Formatting usually only works with the current file so it shouldn't use that much memory that would crash the process. I suspect it might be some infinite loop/recursive call. Can you try copying the problematic files or the prettier config file to an empty svelte-kit project to see if you can reproduce it? If you still can't find a reproduction, please at least provide the dependencies and devDependencies in your package.json, the tsconfig.json/jsconfig.json and the prettier config file.

Extarys commented 1 month ago

I'll get started on some of those right away:

package.json

{
    "devDependencies": {
        "@repo/api-hono": "workspace:*",
        "@repo/dto": "workspace:*",
        "@repo/edgedb": "workspace:*",
        "@fortawesome/fontawesome-pro": "^6.6.0",
        "@fortawesome/free-brands-svg-icons": "^6.6.0",
        "@fortawesome/pro-duotone-svg-icons": "^6.6.0",
        "@fortawesome/pro-light-svg-icons": "^6.6.0",
        "@fortawesome/pro-regular-svg-icons": "^6.6.0",
        "@fortawesome/pro-solid-svg-icons": "^6.6.0",
        "@fortawesome/pro-thin-svg-icons": "^6.6.0",
        "@fortawesome/sharp-duotone-solid-svg-icons": "^6.6.0",
        "@fortawesome/sharp-light-svg-icons": "^6.6.0",
        "@fortawesome/sharp-regular-svg-icons": "^6.6.0",
        "@fortawesome/sharp-solid-svg-icons": "^6.6.0",
        "@fortawesome/sharp-thin-svg-icons": "^6.6.0",
        "@fortawesome/svelte-fontawesome": "^0.2.2",
        "@playwright/test": "^1.28.1",
        "@sveltejs/adapter-auto": "^3.0.0",
        "@sveltejs/kit": "^2.5.26",
        "@sveltejs/vite-plugin-svelte": "^4.0.0-next.6",
        "@types/eslint": "^9.6.0",
        "eslint": "^9.0.0",
        "eslint-config-prettier": "^9.1.0",
        "eslint-plugin-svelte": "^2.36.0",
        "globals": "^15.0.0",
        "prettier": "^3.1.1",
        "prettier-plugin-svelte": "^3.1.2",
        "svelte": "^5.0.0-next.245",
        "svelte-check": "^4.0.0",
        "typescript": "^5.0.0",
        "typescript-eslint": "^8.0.0",
        "vite": "^5.0.3",
        "vitest": "^2.0.0",
        "tailwindcss": "^3.4.4",
        "postcss": "^8.4.38",
        "autoprefixer": "^10.4.19",
        "@tailwindcss/typography": "^0.5.15",
        "prettier-plugin-tailwindcss": "^0.6.4"
    },
    "type": "module",
    "dependencies": {
        "@cartamd/plugin-attachment": "^4.0.2",
        "@cartamd/plugin-code": "^4.0.6",
        "@cartamd/plugin-component": "^1.0.2",
        "@cartamd/plugin-emoji": "^4.1.3",
        "@cartamd/plugin-slash": "^4.0.2",
        "@internationalized/date": "^3.5.5",
        "@paralleldrive/cuid2": "^2.2.2",
        "@tiptap/core": "^2.7.2",
        "@tiptap/extension-dropcursor": "^2.7.2",
        "@tiptap/extension-link": "^2.7.2",
        "@tiptap/extension-underline": "^2.7.2",
        "@tiptap/pm": "^2.7.2",
        "@tiptap/starter-kit": "^2.7.2",
        "bits-ui": "^0.21.13",
        "carta-md": "^4.4.5",
        "clsx": "^2.1.1",
        "cmdk-sv": "^0.0.18",
        "formsnap": "^1.0.1",
        "isomorphic-dompurify": "^2.15.0",
        "lucide-svelte": "^0.439.0",
        "mode-watcher": "^0.4.1",
        "paneforge": "^0.0.5",
        "svelte-fa": "^4.0.2",
        "svelte-persisted-store": "^0.11.0",
        "svelte-tiptap": "^1.1.3",
        "sveltekit-superforms": "^2.17.0",
        "tailwind-merge": "^2.5.2",
        "tailwind-variants": "^0.2.1",
        "zod": "^3.23.8"
    }
}

tsconfig:

{
    "extends": "./.svelte-kit/tsconfig.json",
    "compilerOptions": {
        "allowJs": true,
        "checkJs": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "skipLibCheck": true,
        "sourceMap": true,
        "strict": true,
        "moduleResolution": "bundler"
    }
    // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
    // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files
    //
    // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
    // from the referenced tsconfig.json - TypeScript does not merge them in
}

Prettier

{
    "useTabs": true,
    "singleQuote": true,
    "trailingComma": "none",
    "printWidth": 100,
    "plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
    "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}

Exemple of file that make the extension crash:

<script lang="ts">
    import { zod } from 'sveltekit-superforms/adapters';
    import { goto } from '$app/navigation';
    import SuperDebug, {
        type SuperValidated,
        type Infer,
        superForm,
        setMessage,
        defaults
    } from 'sveltekit-superforms';

    import { loginFormSchema } from '@repo/dto';

    // UI elements
    import * as Card from '$lib/components/ui/card/index.js';
    import * as Form from '$lib/components/ui/form';
    import { Input } from '$lib/components/ui/input';
    import { Button } from '$lib/components/ui/button';

    const form = superForm(defaults(zod(loginFormSchema)), {
        SPA: true,
        resetForm: false,
        validators: zod(loginFormSchema),
        dataType: 'json',
        delayMs: 500,
        timeoutMs: 4000,
        onUpdate: async ({ form }) => {

        }
    });

    const { form: formData, enhance, errors, submitting, delayed, timeout, validate, message } = form;
</script>

<div class="grid place-items-center h-screen shadow">
            <form use:enhance>
        <Card.Root class="flex flex-col w-96 h-96 rounded-sm border shadow-lg">
            <Card.Header>Title</Card.Header>
            <Card.Content>
                <Form.Field {form} name="username">
                    <Form.Control let:attrs>
                        <Form.Label>Username</Form.Label>
                        <Input {...attrs} bind:value={$formData.identifier} />
                    </Form.Control>
                    <Form.FieldErrors />
                </Form.Field>
                <Form.Field {form} name="username">
                    <Form.Control let:attrs>
                        <Form.Label>Password</Form.Label>
                        <Input {...attrs} bind:value={$formData.clearPassword} type="password" />
                    </Form.Control>
                    <Form.FieldErrors />
                </Form.Field>
            </Card.Content>
            <Card.Footer class="flex flex-row">
                <Button type="submit" class="ml-auto">Login</Button>
            </Card.Footer>
        </Card.Root>
    </form>
</div>

<style lang="postcss">
</style>

I'll try to make a reproduction tomorrow ;) But in the meantime maybe there is a hint somewhere in there.

Is there a way to make the extension logs more verbose to help pinpoint the issue?

Extarys commented 1 month ago

I saw a debug option in the svelte extension, it didn't bring much, but I saw some new stuff:

Initialize language server at  file:///Monorepo
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
Initialize new ts service at  /Monorepo/apps/tommy/tsconfig.json
Trying to load configs for /Monorepo/apps/tommy
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
SnapshotManager File Statistics:
Project files: 294
Svelte files: 211
From node_modules: 0
Total: 294
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using svelte-preprocess v5.1.4 from /Monorepo/node_modules/svelte-preprocess
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
apps/tommy/src/lib/components/pages/LoginPage.svelte:57:11 - error TS1003: Identifier expected.

57  formData.
             

Preprocessing failed
Error: [svelte-preprocess] Encountered type error
    at throwError (/Monorepo/node_modules/svelte-preprocess/dist/modules/errors.js:5:11)
    at throwTypescriptError (/Monorepo/node_modules/svelte-preprocess/dist/modules/errors.js:9:28)
    at transpileTs (/Monorepo/node_modules/svelte-preprocess/dist/transformers/typescript.js:215:47)
    at simpleTranspiler (/Monorepo/node_modules/svelte-preprocess/dist/transformers/typescript.js:306:60)
    at transformer (/Monorepo/node_modules/svelte-preprocess/dist/transformers/typescript.js:353:11)
    at transform (/Monorepo/node_modules/svelte-preprocess/dist/autoProcess.js:46:12)
    at async /Monorepo/node_modules/svelte-preprocess/dist/autoProcess.js:117:29
    at async Object.script (/Monorepo/node_modules/svelte-preprocess/dist/autoProcess.js:147:33)
    at async wrappedPreprocessor.script (/home/jer/.vscode-oss/extensions/svelte.svelte-vscode-109.0.1-universal/node_modules/svelte-language-server/dist/src/plugins/svelte/SvelteDocument.js:247:28)
    at async /Monorepo/node_modules/svelte/compiler/index.js:1:688796 {
  __source: 'Script'
}

<--- Last few GCs --->

[3364559:0x1a6c002f8000]    75496 ms: Scavenge 3915.3 (4085.0) -> 3911.2 (4087.2) MB, pooled: 0 MB, 2.73 / 0.00 ms  (average mu = 0.797, current mu = 0.546) allocation failure; 
[3364559:0x1a6c002f8000]    75517 ms: Scavenge 3917.3 (4087.2) -> 3913.4 (4088.5) MB, pooled: 0 MB, 5.40 / 0.00 ms  (average mu = 0.797, current mu = 0.546) allocation failure; 

<--- JS stacktrace --->

FATAL ERROR: NewSpace::EnsureCurrentCapacity Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

[Error - 21:28:21] Server process exited with signal SIGABRT.
[Info  - 21:28:21] Connection to server got closed. Server will restart.
true
Initialize language server at  file:///Monorepo
Initialize new ts service at  /Monorepo/apps/tommy/tsconfig.json
Trying to load configs for /Monorepo/apps/tommy
Loaded config at  /Monorepo/apps/tommy/svelte.config.js
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
SnapshotManager File Statistics:
Project files: 294
Svelte files: 211
From node_modules: 0
Total: 294
Using svelte-preprocess v5.1.4 from /Monorepo/node_modules/svelte-preprocess
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
Executing next invocation of "getSemanticTokens" with low priority
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Executing next invocation of "getCodeLens" with low priority
Using Prettier v3.3.3 from /Monorepo/node_modules/prettier
Executing next invocation of "getSemanticTokens" with low priority
Executing next invocation of "getInlayHints" with low priority
Executing next invocation of "getCodeLens" with low priority
Executing next invocation of "getSemanticTokens" with low priority
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using Prettier v3.3.3 from /Monorepo/node_modules/prettier
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler

<--- Last few GCs --->

[3370243:0x828002f8000]    75534 ms: Scavenge 3916.4 (4085.7) -> 3912.2 (4088.0) MB, pooled: 0 MB, 3.41 / 0.00 ms  (average mu = 0.804, current mu = 0.564) allocation failure; 
[3370243:0x828002f8000]    77793 ms: Mark-Compact 3918.3 (4088.0) -> 3912.4 (4090.2) MB, pooled: 0 MB, 2241.58 / 0.00 ms  (average mu = 0.670, current mu = 0.260) allocation failure; scavenge might not succeed

<--- JS stacktrace --->

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

[Error - 21:30:01] Server process exited with signal SIGABRT.
[Info  - 21:30:01] Connection to server got closed. Server will restart.
true
Initialize language server at  file:///Monorepo
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
Initialize new ts service at  /Monorepo/apps/tommy/tsconfig.json
Trying to load configs for /Monorepo/apps/tommy
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
SnapshotManager File Statistics:
Project files: 294
Svelte files: 211
From node_modules: 0
Total: 294
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using svelte-preprocess v5.1.4 from /Monorepo/node_modules/svelte-preprocess
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler

<--- Last few GCs --->

[3375728:0x2e1c002f8000]    75766 ms: Scavenge 3916.8 (4086.0) -> 3912.6 (4087.7) MB, pooled: 0 MB, 2.63 / 0.00 ms  (average mu = 0.806, current mu = 0.597) allocation failure; 
[3375728:0x2e1c002f8000]    75788 ms: Scavenge 3918.8 (4087.7) -> 3914.8 (4089.2) MB, pooled: 0 MB, 5.35 / 0.00 ms  (average mu = 0.806, current mu = 0.597) allocation failure; 

<--- JS stacktrace --->

FATAL ERROR: NewSpace::EnsureCurrentCapacity Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

[Error - 21:31:38] Server process exited with signal SIGABRT.
[Info  - 21:31:38] Connection to server got closed. Server will restart.
true
Initialize language server at  file:///Monorepo
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
Initialize new ts service at  /Monorepo/apps/tommy/tsconfig.json
Trying to load configs for /Monorepo/apps/tommy
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
SnapshotManager File Statistics:
Project files: 294
Svelte files: 211
From node_modules: 0
Total: 294
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler
Using svelte-preprocess v5.1.4 from /Monorepo/node_modules/svelte-preprocess
No svelte.config.js found. Using https://github.com/sveltejs/svelte-preprocess as fallback
Using Svelte v5.0.0-next.245 from /Monorepo/node_modules/svelte/compiler

<--- Last few GCs --->

[3381131:0x25d4002f8000]    76410 ms: Scavenge 3916.3 (4086.2) -> 3912.2 (4088.0) MB, pooled: 0 MB, 3.33 / 0.00 ms  (average mu = 0.813, current mu = 0.587) allocation failure; 
[3381131:0x25d4002f8000]    78512 ms: Mark-Compact 3918.2 (4088.0) -> 3912.2 (4090.7) MB, pooled: 0 MB, 2086.70 / 0.00 ms  (average mu = 0.688, current mu = 0.274) allocation failure; scavenge might not succeed

<--- JS stacktrace --->

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

[Error - 21:33:20] Server process exited with signal SIGABRT.
[Info  - 21:33:20] Connection to server got closed. Server will restart.
true
Initialize language server at  file:///Monorepo

If I disable and re-enable the extension, it might work (hovering an import to see it's type, etc.) for a bit, else it's making the development with svelte almost impossible.

If possible, please leave this issue open for a while, since the issue could be caused by many things. Hopefully (and sadly) another user might experience this issue too soon...

jasonlyu123 commented 1 month ago

Can follow these steps to collect a cpu profile. At least we could know what was running before memory exploded.

  1. Set the "svelte.language-server.port": config to 9222.
  2. Restart your editor and open a svelte file.
  3. Open Chrome or Edge and type chrome://inspect. Wait a bit. There should be a svelte language server, and you can inspect
  4. A dev tool will open After you click the inspect link. You can record a CPU profile in the performance tab. If the performance tab is empty, click the gear icon on the top right, go to "Experimentals" and disable "Performance panel: enable live metrics landing page"
  5. export the recording. You can open the output file in an editor to remove sensitive info like the username in the file path.
Extarys commented 1 month ago

Hey @jasonlyu123 thanks for your troubleshooting steps, but I'm mostly certain I found the issue... :D

After a lot of fiddling and thinking, I thought the issue could come from Hono RPC client trying to compile the types on the fly. I tried building it but it crashed.

I commented out most of the api code and build the api, uncommenting a bit and adding files each time to make sure it was still compiling.

It started throwing the same GC error when I uncommented a query from edgedb typescript client.

Using edgedb, I was fetching an object 5 levels down.

As soon as I commented that part out, a ton of "problems" in vscode started appearing as soon as I open some files (Since I've been doing stuff for the past 3-4 days basically in a text editor :joy: ) image

Glad it is not a library version or svelte extension causing the problem. Sorry for the scare and thanks for your time <3