svelte: Outros undefined when transitioning to another page

Couldn’t get a REPL repro but If I try to navigate from https://smelte-8z4ib07lj.now.sh/components/tabs to any other page I get this error:

index.mjs:629 Uncaught (in promise) TypeError: Cannot read property 'callbacks' of undefined
    at U (index.mjs:629)
    at Object.o (Waypoint.svelte:116)
    at hn (index.mjs:761)
    at Object.o (Image.svelte:27)
    at hn (index.mjs:761)
    at Object.o (tabs.c766b77c.js:1)
    at hn (index.mjs:761)
    at Object.o (TabButton.svelte:11)
    at hn (index.mjs:761)
    at Object.o (Tab.svelte:6)
</details>

At this line:

function transition_out(block, local, callback) {
    if (block && block.o) {
        if (outroing.has(block))
            return;
        outroing.add(block);
        **outros.callbacks.push(() => {**
            outroing.delete(block);
            if (callback) {
                block.d(1);
                callback();
            }
        });
        block.o(local);
    }
}

Works https://smelte-8z4ib07lj.now.sh/components/tabs

Doesn’t https://smelte-ocubxglhw.now.sh/components/tabs

Not sure what causes the error so I simply patched it by adding an extra check if outros.callbacks is set.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 3
  • Comments: 83 (28 by maintainers)

Commits related to this issue

Most upvoted comments

Hello, not sure why this issue is closed. Seems to still be a problem (using webpack and sapper). I’ve tried almost all of the solutions on this page and the only one working for me is from @QuickMick

{#each [...[]] as _}
  <div />
{:else}
  <ComponentFromOtherPackage  />
{/each}

I can also confirm that the bug is still present in 3.28.0 and the workaround from @srinivasrk works. Until the bug is fixed, you can use @rollup/plugin-replace to automate this workaround

plugins: [
  replace({
    'outros.c.push': 'if (outros === undefined) { block.o(local); return }\noutros.c.push'
  }),
]

I know it is ugly and might break sometimes or something else, but it works for now (for me)…

Issue is back as of 3.12.1, I am getting this error now when trying to transition to another page.

Cannot read property 'c' of undefined

function transition_out(block, local, detach, callback) {
    if (block && block.o) {
        if (outroing.has(block))
            return;
        outroing.add(block);
        outros.c.push(() => {
            outroing.delete(block);
            if (callback) {
                if (detach)
                    block.d(1);
                callback();
            }
        });
        block.o(local);
    }
}

I still get it if I try to import a component like this from a third party package.

{#if true}
  <slot/>
{/if}

For anyone who comes to this thread because they’ve gotten the TypeError: Cannot read property 'c' of undefined while running tests with Jest, I’ve solved this by setting an alias in jest.config.js:

  moduleNameMapper: {
    "^svelte(.*)$": "<rootDir>/node_modules/svelte$1"
  },

Can we get an update on this? I’m still struggling with this issue on Svelte version 3.24.1

Still having this issue with webpack and rollup(3.35.0), consuming an external component, if wrapped in a IF clause, it will produce the outro error, even tho we are not using a transition animation.

@alanleite I had the same issue and found that it was fixed by reverting to 3.38.2

same problem for me:

"Uncaught (in promise) TypeError: Cannot read property 'c' of undefined" 

with “svelte”: “^3.0.0” and rollup.

I wanted to make a moduler design. I compiled main.js and bunch of apps seperately and individually. when apps loaded, they send themselves with custom event like this:

...
// an app.js
const register = new CustomEvent(
  "REGISTER_APP",
  {
    bubbles: true,
    detail: appComponent,
  }
)
document.dispatchEvent(register);

main.js listens these app register events and render a tab for each app. but, if the incoming “app” component includes any other nested component, the error occurs. for example when you switch tabs, the destroyed app component gives error:

...

    function transition_out(block, local, detach, callback) {
        if (block && block.o) {
            if (outroing.has(block))
                return;
            outroing.add(block);
            outros.c.push(() => { // this push part gives the error
                outroing.delete(block);
                if (callback) {
                    if (detach)
                        block.d(1);
                    callback();
                }
            });
            block.o(local);
        }
    }
...

any solution for this type of situation?

EDIT: temporary solution

...

-          outros.c.push(() => { // this push part gives the error
+          outros?.c?.push(() => { 

...

Still an issue in 3.31.0. In addition to @nick-legmann workaround, you can use patch-package if you’ve already got it installed.

I’m still having this issue on Svelte 3.7.1.

I have a component project, then I have an examples subdirectory that contains an app project. From the root project I run npm link then from the examples subdirectory I run npm link <project-name>. Everything compiles and runs correctly, but when I try to switch tabs in my app (using svelte-tabs), I get the TypeError: Cannot read property 'c' of undefined error.

Repo is here: https://github.com/joeattardi/svelte-emoji-picker

Same problem here using the latest Svelte version… Should re-open this issue?

idk if this is helpful at all to solve this bug, but i do not get this error, when i have my external component wrapped inside the else case of an each. the problem persist, when “ComponentFromOtherPackage” is used in the each case, or without the each at all.

{#each [...[]] as _}
  <div />
{:else}
      <ComponentFromOtherPackage  />
{/each}

I’ve gotten this a few times and I forgot how I worked around. So this time I wanted to add a note. In a few days I can post a repro repo.

{#if $routeVisible}<slot/>{/if} SSR will do this but sometimes the client gets the outros error. It has to do with a router component in my case. My guess is that it disappears and outros tries to do something with it but it’s gone.

My work around for client-side is: <div class:hidden={!$routeVisible}><slot /></div>.

Maybe outros can do if element still exists do outro.

Ok, I have some more information. Currently this app is using the svelte-tabs npm package. If, instead of importing the svelte-tabs module, I just add the source code from svelte-tabs into the app’s source code - so it’s part of the same project - everything works.

So it seems the issue is having a third party Svelte component that imports another third party Svelte component, that must be why things are getting duplicated.

I had a similar issue using the package Svelma when transitioning to another page. (https://github.com/c0bra/svelma/issues/18)

Using a Button imported using import { Button } from 'svelma' would fail in the same place as this issue with transition outros being undefined

Using a Button imported using import Button from 'svelma/src/components/Button.svelte' would not cause an issue.

Here is a repro repo: https://github.com/rohfle/svelma-button-issue-poc

While it doesn’t address the root of the problem- out of curiousity- is there a particular reason why checking for c first is a bad idea? Would something like c && or if (c) outros.c.push(() => { have negative consequences of some sort?

I’ve triggered this a couple of times with svelte-kit also. Not sure what the reason is, but at least the error message could be better…

Setting config.kit.vite.build.rollupOptions.dedupe doesn’t help

I started debugging this by checking out commits in the history, and when I went back to the version that produces the error, the error no longer happens. Bizarre…

@dimfeld ok nevermind it worked. My problem was that I installed my dependency for development like "@xxx/shared": "file:../../shared". When I actually installed it from our repo it works with dedupe: ['svelte']. Thanks for the tipp!

@dummdidumm the latest version of svelte hasn’t fixed it yet it seems.

See this line https://github.com/sveltejs/svelte/blob/68538c61eb093fb73fb1881948cc21a6789a1d53/src/runtime/internal/transitions.ts#L56

It still doesn’t have that check for outros.

@quantuminformation It should be under /node_modules/svelte/internal/index.mjs

image

I added the line in red.

I don’t really see a way to have a nicer error message here. The issue here is how dependencies are getting resolved during bundling, and neither the Svelte compiler nor the bundler plugin have any awareness as to how that’s happening. The right answer is probably to just put the above bit of configuration in template-webpack and in svelte-loader’s readme, which we’re probably about ready to do now.

https://github.com/sveltejs/svelte-loader#resolvemainfields You need resolve.mainFields. Not having this will cause the same problem that npm/yarn linking does - you have two copies of the Svelte shared internals in your app, which causes various issues.

I’m surprised this wasn’t in the template yet in https://github.com/sveltejs/template-webpack/blob/master/webpack.config.js - I’ll add it.

Still getting this exact issue on 3.6.7. Only happens on external components (yarn linked in this case), if i use local components issue is resolved. Can’t recreate in REPL. I’ve double checked all versions of Svelte are the same. Built using Webpack 4, yarn 1.16.0 and node v12.

This one is NASTY!