{"record":{"id":"99cce3cedf624b47","repo":"sveltejs/svelte","slug":"this-migration-would-change-the-name-of-a-slot-99cce3","errorCode":null,"errorMessage":"This migration would change the name of a slot (${name} to ${new_name}) making the component unusable","messagePattern":"This migration would change the name of a slot \\((.+?) to (.+?)\\) making the component unusable","errorType":"exception","errorClass":"MigrationError","httpStatus":null,"severity":"warning","filePath":"packages/svelte/src/compiler/migrate/index.js","lineNumber":1888,"sourceCode":"\t} else if (node.name === '$$restProps' && state.analysis.uses_rest_props) {\n\t\tstate.str.update(\n\t\t\t/** @type {number} */ (node.start),\n\t\t\t/** @type {number} */ (node.end),\n\t\t\tstate.names.rest\n\t\t);\n\t} else if (node.name === '$$slots' && state.analysis.uses_slots) {\n\t\tif (parent?.type === 'MemberExpression') {\n\t\t\tif (state.analysis.custom_element) return;\n\n\t\t\tlet name = parent.property.type === 'Literal' ? parent.property.value : parent.property.name;\n\t\t\tlet slot_name = name;\n\t\t\tconst existing_prop = state.props.find((prop) => prop.slot_name === name);\n\t\t\tif (existing_prop) {\n\t\t\t\tname = existing_prop.local;\n\t\t\t} else if (name !== 'default') {\n\t\t\t\tlet new_name = state.scope.generate(name);\n\t\t\t\tif (new_name !== name) {\n\t\t\t\t\tthrow new MigrationError(\n\t\t\t\t\t\t`This migration would change the name of a slot (${name} to ${new_name}) making the component unusable`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tname = name === 'default' ? 'children' : name;\n\n\t\t\tif (!existing_prop) {\n\t\t\t\tstate.props.push({\n\t\t\t\t\tlocal: name,\n\t\t\t\t\texported: name,\n\t\t\t\t\tinit: '',\n\t\t\t\t\tbindable: false,\n\t\t\t\t\toptional: true,\n\t\t\t\t\tslot_name,\n\t\t\t\t\t// if it's the first time we encounter this slot\n\t\t\t\t\t// we start with any and delegate to when the slot\n\t\t\t\t\t// is actually rendered (it might not happen in that case)","sourceCodeStart":1870,"sourceCodeEnd":1906,"githubUrl":"https://github.com/sveltejs/svelte/blob/20b341f10048cf1016a2028ac7eee5595cfef6a5/packages/svelte/src/compiler/migrate/index.js#L1870-L1906","documentation":"Same slot-rename guard as error 7, but for the `$$slots` object access path (legacy programmatic slot declaration) rather than `<slot name=...>` markup. Triggered when `state.scope.generate(name)` cannot return the original slot name because it is already in scope, and renaming would break consumers.","triggerScenarios":"Running `migrate()` on a Svelte 4 component that reads `$$slots.foo` (programmatic slot access) where `foo` is taken in scope, so `scope.generate(name)` deduplicates it. The check fires only when `state.analysis.uses_slots` is true and the parent is a `MemberExpression`.","commonSituations":"Components that introspect slots dynamically via `$$slots`, e.g. conditional slot rendering using `if ($$slots.header)`. Common in framework/layout components that adapt to which slots the consumer provides.","solutions":["Rename the in-scope identifier that collides with the slot name and re-run migrate.","Convert the `$$slots` usage to explicit snippet props by hand (`let { header } = $props()` then `{@render header?.()}`).","Rename the slot (and all consumers) before migrating so the generated name is stable."],"exampleFix":"// before\n<script>\n  let header = something();\n  if ($$slots.header) { /* ... */ }\n</script>\n\n// after (manual)\n<script>\n  let { header } = $props();\n  if (header) { /* ... */ }\n</script>","handlingStrategy":"validation","validationCode":"// Detect $$slots member access whose names collide with in-scope identifiers.\nfunction slotsAccessCollisions(source) {\n  const names = [...source.matchAll(/\\$\\$slots\\.(\\w+)/g)].map(m => m[1]);\n  const idents = [...source.matchAll(/\\b(?:let|const|var|function|import)\\s+([\\w$]+)/g)].map(m => m[1]);\n  return names.filter(n => idents.includes(n));\n}","typeGuard":null,"tryCatchPattern":"const { code } = migrate({ filename, source });\nif (code.startsWith('<!-- @migration-task') && /migration would change the name of a slot/i.test(code)) {\n  // hand-migrate: `let { slotName } = $props()` and `{@render slotName?.()}`\n}","preventionTips":["Avoid `$$slots.foo` introspection in Svelte 4 — render slots unconditionally or with explicit flags.","Reserve slot names as prop names so the migrator can map them without renaming.","Audit dynamic slot usage before migrating layout/framework components."],"tags":["svelte5","migration","slots","snippets","naming-collision","codemod"],"backgroundTag":null,"analyzedSha":"20b341f10048cf1016a2028ac7eee5595cfef6a5","analyzedAt":"2026-08-12T23:37:30.399Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}