docs: more details for errors/warnings on the site ()

* docs: more details for errors/warnings on the site

Related to 

* Apply suggestions from code review

Co-authored-by: Rich Harris <rich.harris@vercel.com>

* fix in correct place

* tab not spaces

* tweaks

* fix

* Apply suggestions from code review

* regenerate

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/14635/head
Simon H 4 months ago committed by GitHub
parent 11764632b9
commit c6fca02009
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -66,6 +66,31 @@ The easiest way to log a value as it changes over time is to use the [`$inspect`
The `%attribute%` attribute on `%html%` changed its value between server and client renders. The client value, `%value%`, will be ignored in favour of the server value
```
Certain attributes like `src` on an `<img>` element will not be repaired during hydration, i.e. the server value will be kept. That's because updating these attributes can cause the image to be refetched (or in the case of an `<iframe>`, for the frame to be reloaded), even if they resolve to the same resource.
To fix this, either silence the warning with a [`svelte-ignore`](basic-markup#Comments) comment, or ensure that the value stays the same between server and client. If you really need the value to change on hydration, you can force an update like this:
```svelte
<script>
let { src } = $props();
if (typeof window !== 'undefined') {
// stash the value...
const initial = src;
// unset it...
src = undefined;
$effect(() => {
// ...and reset after we've mounted
src = initial;
});
}
</script>
<img {src} />
```
### hydration_html_changed
```
@ -76,6 +101,31 @@ The value of an `{@html ...}` block changed between server and client renders. T
The value of an `{@html ...}` block %location% changed between server and client renders. The client value will be ignored in favour of the server value
```
If the `{@html ...}` value changes between the server and the client, it will not be repaired during hydration, i.e. the server value will be kept. That's because change detection during hydration is expensive and usually unnecessary.
To fix this, either silence the warning with a [`svelte-ignore`](basic-markup#Comments) comment, or ensure that the value stays the same between server and client. If you really need the value to change on hydration, you can force an update like this:
```svelte
<script>
let { markup } = $props();
if (typeof window !== 'undefined') {
// stash the value...
const initial = markup;
// unset it...
markup = undefined;
$effect(() => {
// ...and reset after we've mounted
markup = initial;
});
}
</script>
{@html markup}
```
### hydration_mismatch
```
@ -86,6 +136,10 @@ Hydration failed because the initial UI does not match what was rendered on the
Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near %location%
```
This warning is thrown when Svelte encounters an error while hydrating the HTML from the server. During hydration, Svelte walks the DOM, expecting a certain structure. If that structure is different (for example because the HTML was repaired by the DOM because of invalid HTML), then Svelte will run into issues, resulting in this warning.
During development, this error is often preceeded by a `console.error` detailing the offending HTML, which needs fixing.
### invalid_raw_snippet_render
```
@ -110,6 +164,10 @@ Tried to unmount a component that was not mounted
%parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
```
Consider three components `GrandParent`, `Parent` and `Child`. If you do `<GrandParent bind:value>`, inside `GrandParent` pass on the variable via `<Parent {value} />` (note the missing `bind:`) and then do `<Child bind:value>` inside `Parent`, this warning is thrown.
To fix it, `bind:` to the value instead of just passing a property (i.e. in this example do `<Parent bind:value />`).
### ownership_invalid_mutation
```
@ -120,6 +178,32 @@ Mutating a value outside the component that created it is strongly discouraged.
%component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
```
Consider the following code:
```svelte
<!--- file: App.svelte --->
<script>
import Child from './Child.svelte';
let person = $state({ name: 'Florida', surname: 'Man' });
</script>
<Child {person} />
```
```svelte
<!--- file: Child.svelte --->
<script>
let { person } = $props();
</script>
<input bind:value={person.name}>
<input bind:value={person.surname}>
```
`Child` is mutating `person` which is owned by `App` without being explicitly "allowed" to do so. This is strongly discouraged since it can create code that is hard to reason about at scale ("who mutated this value?"), hence the warning.
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
### reactive_declaration_non_reactive_property
```

@ -610,6 +610,20 @@ Empty block
Unused CSS selector "%name%"
```
Svelte traverses both the template and the `<style>` tag to find out which of the CSS selectors are not used within the template, so it can remove them.
In some situations a selector may target an element that is not 'visible' to the compiler, for example because it is part of an `{@html ...}` tag or you're overriding styles in a child component. In these cases, use [`:global`](/docs/svelte/global-styles) to preserve the selector as-is:
```svelte
<div class="post">{@html content}</div>
<style>
.post :global {
p {...}
}
</style>
```
### element_invalid_self_closing_tag
```
@ -622,6 +636,8 @@ Self-closing HTML tags for non-void elements are ambiguous — use `<%name% ...>
Using `on:%name%` to listen to the %name% event is deprecated. Use the event attribute `on%name%` instead
```
See [the migration guide](v5-migration-guide#Event-changes) for more info.
### export_let_unused
```
@ -640,6 +656,8 @@ Component has unused export property '%name%'. If it is for external reference o
Svelte 5 components are no longer classes. Instantiate them using `mount` or `hydrate` (imported from 'svelte') instead.
```
See the [migration guide](v5-migration-guide#Components-are-no-longer-classes) for more info.
### node_invalid_placement_ssr
```
@ -660,6 +678,30 @@ This code will work when the component is rendered on the client (which is why t
`%name%` is updated, but is not declared with `$state(...)`. Changing its value will not correctly trigger updates
```
This warning is thrown when the compiler detects the following:
- a variable was declared without `$state` or `$state.raw`
- the variable is reassigned
- the variable is read in a reactive context
In this case, changing the value will not correctly trigger updates. Example:
```svelte
<script>
let reactive = $state('reactive');
let stale = 'stale';
</script>
<p>This value updates: {reactive}</p>
<p>This value does not update: {stale}</p>
<button onclick={() => {
stale = 'updated';
reactive = 'updated';
}}>update</button>
```
To fix this, wrap your variable declaration with `$state`.
### options_deprecated_accessors
```
@ -732,6 +774,12 @@ Reassignments of module-level declarations will not cause reactive statements to
`context="module"` is deprecated, use the `module` attribute instead
```
```svelte
<script ---context="module"--- +++context+++>
let foo = 'bar';
</script>
```
### script_unknown_attribute
```
@ -744,12 +792,79 @@ Unrecognized attribute — should be one of `generics`, `lang` or `module`. If t
Using `<slot>` to render parent content is deprecated. Use `{@render ...}` tags instead
```
See [the migration guide](v5-migration-guide#Snippets-instead-of-slots) for more info.
### state_referenced_locally
```
State referenced in its own scope will never update. Did you mean to reference it inside a closure?
```
This warning is thrown when the compiler detects the following:
- A reactive variable is declared
- the variable is reassigned
- the variable is referenced inside the same scope it is declared and it is a non-reactive context
In this case, the state reassignment will not be noticed by whatever you passed it to. For example, if you pass the state to a function, that function will not notice the updates:
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
let count = $state(0);
// warning: state_referenced_locally
setContext('count', count);
</script>
<button onclick={() => count++}>
increment
</button>
```
```svelte
<!--- file: Child.svelte --->
<script>
import { getContext } from 'svelte';
const count = getContext('count');
</script>
<!-- This will never update -->
<p>The count is {count}</p>
```
To fix this, reference the variable such that it is lazily evaluated. For the above example, this can be achieved by wrapping `count` in a function:
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
let count = $state(0);
setContext('count', +++() => count+++);
</script>
<button onclick={() => count++}>
increment
</button>
```
```svelte
<!--- file: Child.svelte --->
<script>
import { getContext } from 'svelte';
const count = getContext('count');
</script>
<!-- This will update -->
<p>The count is {+++count()+++}</p>
```
For more info, see [Passing state into functions]($state#Passing-state-into-functions).
### store_rune_conflict
```
@ -805,6 +920,8 @@ A derived value may be used in other contexts:
`<svelte:self>` is deprecated — use self-imports (e.g. `import %name% from './%basename%'`) instead
```
See [the note in the docs](legacy-svelte-self) for more info.
### unknown_code
```

@ -5,3 +5,5 @@
```
`%name%(...)` is not available on the server
```
Certain methods such as `mount` cannot be invoked while running in a server context. Avoid calling them eagerly, i.e. not during render.

@ -6,12 +6,54 @@
Cannot use `{@render children(...)}` if the parent component uses `let:` directives. Consider using a named snippet instead
```
This error would be thrown in a setup like this:
```svelte
<!--- file: Parent.svelte --->
<List {items} let:entry>
<span>{entry}</span>
</List>
```
```svelte
<!--- file: List.svelte --->
<script>
let { items, children } = $props();
</script>
<ul>
{#each items as item}
<li>{@render children(item)}</li>
{/each}
</ul>
```
Here, `List.svelte` is using `{@render children(item)` which means it expects `Parent.svelte` to use snippets. Instead, `Parent.svelte` uses the deprecated `let:` directive. This combination of APIs is incompatible, hence the error.
### lifecycle_outside_component
```
`%name%(...)` can only be used during component initialisation
```
Certain lifecycle methods can only be used during component initialisation. To fix this, make sure you're invoking the method inside the _top level of the instance script_ of your component.
```svelte
<script>
import { onMount } from 'svelte';
function handleClick() {
// This is wrong
onMount(() => {})
}
// This is correct
onMount(() => {})
</script>
<button onclick={handleClick}>click me</button>
```
### store_invalid_shape
```

@ -6,6 +6,8 @@
`<svelte:element this="%tag%">` is a void element — it cannot have content
```
Elements such as `<input>` cannot have content, any children passed to these elements will be ignored.
### state_snapshot_uncloneable
```
@ -17,3 +19,10 @@ The following properties cannot be cloned with `$state.snapshot` — the return
%properties%
```
`$state.snapshot` tries to clone the given value in order to return a reference that no longer changes. Certain objects may not be cloneable, in which case the original value is returned. In the following example, `property` is cloned, but `window` is not, because DOM elements are uncloneable:
```js
const state = $state({ property: 'this is cloneable', window })
const snapshot = $state.snapshot();
```

@ -52,18 +52,72 @@ The easiest way to log a value as it changes over time is to use the [`$inspect`
> The `%attribute%` attribute on `%html%` changed its value between server and client renders. The client value, `%value%`, will be ignored in favour of the server value
Certain attributes like `src` on an `<img>` element will not be repaired during hydration, i.e. the server value will be kept. That's because updating these attributes can cause the image to be refetched (or in the case of an `<iframe>`, for the frame to be reloaded), even if they resolve to the same resource.
To fix this, either silence the warning with a [`svelte-ignore`](basic-markup#Comments) comment, or ensure that the value stays the same between server and client. If you really need the value to change on hydration, you can force an update like this:
```svelte
<script>
let { src } = $props();
if (typeof window !== 'undefined') {
// stash the value...
const initial = src;
// unset it...
src = undefined;
$effect(() => {
// ...and reset after we've mounted
src = initial;
});
}
</script>
<img {src} />
```
## hydration_html_changed
> The value of an `{@html ...}` block changed between server and client renders. The client value will be ignored in favour of the server value
> The value of an `{@html ...}` block %location% changed between server and client renders. The client value will be ignored in favour of the server value
If the `{@html ...}` value changes between the server and the client, it will not be repaired during hydration, i.e. the server value will be kept. That's because change detection during hydration is expensive and usually unnecessary.
To fix this, either silence the warning with a [`svelte-ignore`](basic-markup#Comments) comment, or ensure that the value stays the same between server and client. If you really need the value to change on hydration, you can force an update like this:
```svelte
<script>
let { markup } = $props();
if (typeof window !== 'undefined') {
// stash the value...
const initial = markup;
// unset it...
markup = undefined;
$effect(() => {
// ...and reset after we've mounted
markup = initial;
});
}
</script>
{@html markup}
```
## hydration_mismatch
> Hydration failed because the initial UI does not match what was rendered on the server
> Hydration failed because the initial UI does not match what was rendered on the server. The error occurred near %location%
This warning is thrown when Svelte encounters an error while hydrating the HTML from the server. During hydration, Svelte walks the DOM, expecting a certain structure. If that structure is different (for example because the HTML was repaired by the DOM because of invalid HTML), then Svelte will run into issues, resulting in this warning.
During development, this error is often preceeded by a `console.error` detailing the offending HTML, which needs fixing.
## invalid_raw_snippet_render
> The `render` function passed to `createRawSnippet` should return HTML for a single element
@ -80,12 +134,42 @@ The easiest way to log a value as it changes over time is to use the [`$inspect`
> %parent% passed a value to %child% with `bind:`, but the value is owned by %owner%. Consider creating a binding between %owner% and %parent%
Consider three components `GrandParent`, `Parent` and `Child`. If you do `<GrandParent bind:value>`, inside `GrandParent` pass on the variable via `<Parent {value} />` (note the missing `bind:`) and then do `<Child bind:value>` inside `Parent`, this warning is thrown.
To fix it, `bind:` to the value instead of just passing a property (i.e. in this example do `<Parent bind:value />`).
## ownership_invalid_mutation
> Mutating a value outside the component that created it is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
> %component% mutated a value owned by %owner%. This is strongly discouraged. Consider passing values to child components with `bind:`, or use a callback instead
Consider the following code:
```svelte
<!--- file: App.svelte --->
<script>
import Child from './Child.svelte';
let person = $state({ name: 'Florida', surname: 'Man' });
</script>
<Child {person} />
```
```svelte
<!--- file: Child.svelte --->
<script>
let { person } = $props();
</script>
<input bind:value={person.name}>
<input bind:value={person.surname}>
```
`Child` is mutating `person` which is owned by `App` without being explicitly "allowed" to do so. This is strongly discouraged since it can create code that is hard to reason about at scale ("who mutated this value?"), hence the warning.
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
## reactive_declaration_non_reactive_property
> A `$:` statement (%location%) read reactive state that was not visible to the compiler. Updates to this state will not cause the statement to re-run. The behaviour of this code will change if you migrate it to runes mode

@ -6,10 +6,36 @@
> Svelte 5 components are no longer classes. Instantiate them using `mount` or `hydrate` (imported from 'svelte') instead.
See the [migration guide](v5-migration-guide#Components-are-no-longer-classes) for more info.
## non_reactive_update
> `%name%` is updated, but is not declared with `$state(...)`. Changing its value will not correctly trigger updates
This warning is thrown when the compiler detects the following:
- a variable was declared without `$state` or `$state.raw`
- the variable is reassigned
- the variable is read in a reactive context
In this case, changing the value will not correctly trigger updates. Example:
```svelte
<script>
let reactive = $state('reactive');
let stale = 'stale';
</script>
<p>This value updates: {reactive}</p>
<p>This value does not update: {stale}</p>
<button onclick={() => {
stale = 'updated';
reactive = 'updated';
}}>update</button>
```
To fix this, wrap your variable declaration with `$state`.
## perf_avoid_inline_class
> Avoid 'new class' — instead, declare the class at the top level scope
@ -30,6 +56,71 @@
> State referenced in its own scope will never update. Did you mean to reference it inside a closure?
This warning is thrown when the compiler detects the following:
- A reactive variable is declared
- the variable is reassigned
- the variable is referenced inside the same scope it is declared and it is a non-reactive context
In this case, the state reassignment will not be noticed by whatever you passed it to. For example, if you pass the state to a function, that function will not notice the updates:
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
let count = $state(0);
// warning: state_referenced_locally
setContext('count', count);
</script>
<button onclick={() => count++}>
increment
</button>
```
```svelte
<!--- file: Child.svelte --->
<script>
import { getContext } from 'svelte';
const count = getContext('count');
</script>
<!-- This will never update -->
<p>The count is {count}</p>
```
To fix this, reference the variable such that it is lazily evaluated. For the above example, this can be achieved by wrapping `count` in a function:
```svelte
<!--- file: Parent.svelte --->
<script>
import { setContext } from 'svelte';
let count = $state(0);
setContext('count', +++() => count+++);
</script>
<button onclick={() => count++}>
increment
</button>
```
```svelte
<!--- file: Child.svelte --->
<script>
import { getContext } from 'svelte';
const count = getContext('count');
</script>
<!-- This will update -->
<p>The count is {+++count()+++}</p>
```
For more info, see [Passing state into functions]($state#Passing-state-into-functions).
## store_rune_conflict
> It looks like you're using the `$%name%` rune, but there is a local binding called `%name%`. Referencing a local variable with a `$` prefix will create a store subscription. Please rename `%name%` to avoid the ambiguity

@ -1,3 +1,17 @@
## css_unused_selector
> Unused CSS selector "%name%"
Svelte traverses both the template and the `<style>` tag to find out which of the CSS selectors are not used within the template, so it can remove them.
In some situations a selector may target an element that is not 'visible' to the compiler, for example because it is part of an `{@html ...}` tag or you're overriding styles in a child component. In these cases, use [`:global`](/docs/svelte/global-styles) to preserve the selector as-is:
```svelte
<div class="post">{@html content}</div>
<style>
.post :global {
p {...}
}
</style>
```

@ -38,6 +38,8 @@
> Using `on:%name%` to listen to the %name% event is deprecated. Use the event attribute `on%name%` instead
See [the migration guide](v5-migration-guide#Event-changes) for more info.
## node_invalid_placement_ssr
> %message%. When rendering this component on the server, the resulting HTML will be modified by the browser (by moving, removing, or inserting elements), likely resulting in a `hydration_mismatch` warning
@ -54,6 +56,12 @@ This code will work when the component is rendered on the client (which is why t
> `context="module"` is deprecated, use the `module` attribute instead
```svelte
<script ---context="module"--- +++context+++>
let foo = 'bar';
</script>
```
## script_unknown_attribute
> Unrecognized attribute — should be one of `generics`, `lang` or `module`. If this exists for a preprocessor, ensure that the preprocessor removes it
@ -62,6 +70,8 @@ This code will work when the component is rendered on the client (which is why t
> Using `<slot>` to render parent content is deprecated. Use `{@render ...}` tags instead
See [the migration guide](v5-migration-guide#Snippets-instead-of-slots) for more info.
## svelte_component_deprecated
> `<svelte:component>` is deprecated in runes mode — components are dynamic by default
@ -104,3 +114,5 @@ A derived value may be used in other contexts:
## svelte_self_deprecated
> `<svelte:self>` is deprecated — use self-imports (e.g. `import %name% from './%basename%'`) instead
See [the note in the docs](legacy-svelte-self) for more info.

@ -1,3 +1,5 @@
## lifecycle_function_unavailable
> `%name%(...)` is not available on the server
Certain methods such as `mount` cannot be invoked while running in a server context. Avoid calling them eagerly, i.e. not during render.

@ -2,10 +2,52 @@
> Cannot use `{@render children(...)}` if the parent component uses `let:` directives. Consider using a named snippet instead
This error would be thrown in a setup like this:
```svelte
<!--- file: Parent.svelte --->
<List {items} let:entry>
<span>{entry}</span>
</List>
```
```svelte
<!--- file: List.svelte --->
<script>
let { items, children } = $props();
</script>
<ul>
{#each items as item}
<li>{@render children(item)}</li>
{/each}
</ul>
```
Here, `List.svelte` is using `{@render children(item)` which means it expects `Parent.svelte` to use snippets. Instead, `Parent.svelte` uses the deprecated `let:` directive. This combination of APIs is incompatible, hence the error.
## lifecycle_outside_component
> `%name%(...)` can only be used during component initialisation
Certain lifecycle methods can only be used during component initialisation. To fix this, make sure you're invoking the method inside the _top level of the instance script_ of your component.
```svelte
<script>
import { onMount } from 'svelte';
function handleClick() {
// This is wrong
onMount(() => {})
}
// This is correct
onMount(() => {})
</script>
<button onclick={handleClick}>click me</button>
```
## store_invalid_shape
> `%name%` is not a store with a `subscribe` method

@ -2,6 +2,8 @@
> `<svelte:element this="%tag%">` is a void element — it cannot have content
Elements such as `<input>` cannot have content, any children passed to these elements will be ignored.
## state_snapshot_uncloneable
> Value cannot be cloned with `$state.snapshot` — the original value was returned
@ -9,3 +11,10 @@
> The following properties cannot be cloned with `$state.snapshot` — the return value contains the originals:
>
> %properties%
`$state.snapshot` tries to clone the given value in order to return a reference that no longer changes. Certain objects may not be cloneable, in which case the original value is returned. In the following example, `property` is cloned, but `window` is not, because DOM elements are uncloneable:
```js
const state = $state({ property: 'this is cloneable', window })
const snapshot = $state.snapshot();
```

Loading…
Cancel
Save