gatsbyjs/gatsby · error · SlicePropsError

Slice "${sliceName}" was passed props that are not serializa

Error message

Slice "${sliceName}" was passed props that are not serializable (${errors}).

What it means

Thrown as a SlicePropsError when the <Slice> component receives props that are not serializable. Gatsby Slices render components in a separate pass and pass data via serialization (especially in SSR/DSG), so all props must be JSON-serializable. validateSliceProps recursively checks each prop; if any value is a function, or contains a function deep in its structure, the error lists all offending prop paths.

Source

Thrown at packages/gatsby/cache-dir/slice.js:23

import { InlineSlice } from "./slice/inline-slice"
import { SlicesContext } from "./slice/context"

export function Slice(props) {
  if (process.env.GATSBY_SLICES) {
    // we use sliceName internally, so remap alias to sliceName
    const internalProps = {
      ...props,
      sliceName: props.alias,
    }
    delete internalProps.alias
    delete internalProps.__renderedByLocation

    const slicesContext = useContext(SlicesContext)

    // validate props
    const propErrors = validateSliceProps(props)
    if (Object.keys(propErrors).length) {
      throw new SlicePropsError(
        slicesContext.renderEnvironment === `browser`,
        internalProps.sliceName,
        propErrors,
        props.__renderedByLocation
      )
    }

    if (slicesContext.renderEnvironment === `server`) {
      return <ServerSlice {...internalProps} />
    } else if (slicesContext.renderEnvironment === `browser`) {
      // in the browser, we'll just render the component as is
      return <InlineSlice {...internalProps} />
    } else if (
      slicesContext.renderEnvironment === `engines` ||
      slicesContext.renderEnvironment === `dev-ssr`
    ) {
      // if we're in SSR, we'll just render the component as is
      return <InlineSlice {...internalProps} />

View on GitHub (pinned to 8b06340921)

Solutions

  1. Remove all function-typed props from <Slice> — move event handlers into the Slice component itself or use a context/callback approach inside the Slice.
  2. Ensure only plain objects, arrays, strings, numbers, booleans, and null are passed as Slice props.
  3. If you need to pass complex data, serialize it first (e.g. Date.toISOString()).
  4. Review the error message: it lists each non-serializable prop path (e.g. 'onClick', 'config.render').

Example fix

// before — passing a function to a Slice
<Slice alias="header" onMenuClick={() => setOpen(true)} />

// after — move interactivity inside the Slice component
// In the slice component itself:
export default function Header() {
  const [open, setOpen] = useState(false)
  return <nav onClick={() => setOpen(!open)}>...</nav>
}
// Usage: <Slice alias="header" />  // no function props
Defensive patterns

Strategy: validation

Validate before calling

// Validate Slice props are serializable before passing
function isSerializable(value, seen = new WeakSet()) {
  if (value === null || value === undefined) return true
  const t = typeof value
  if (t === 'string' || t === 'number' || t === 'boolean') return true
  if (t === 'function') return false
  if (t === 'object') {
    if (seen.has(value)) return true // circular ref, treat as OK for this check
    seen.add(value)
    return Object.values(value).every(v => isSerializable(v, seen))
  }
  return false
}

// Usage before rendering:
if (!isSerializable(sliceProps)) {
  console.error('Slice props contain non-serializable values')
}

Type guard

// Type guard: ensure Slice props are plain serializable data
type Serializable = string | number | boolean | null | Serializable[] | { [k: string]: Serializable }

function isSerializableProps(props: unknown): props is Serializable {
  if (props === null || props === undefined) return true
  const t = typeof props
  if (t === 'string' || t === 'number' || t === 'boolean') return true
  if (t === 'function') return false
  if (Array.isArray(props)) return props.every(isSerializableProps)
  if (t === 'object') return Object.values(props).every(isSerializableProps)
  return false
}

Prevention

When it happens

Trigger: A <Slice alias='header' /> call passes a function as a prop (e.g. onClick, render prop), an object containing methods, a React element (which has internal functions), or a class instance. validateSliceProps traverses the entire prop tree and collects all non-serializable paths before throwing.

Common situations: Passing event handlers (onClick, onChange) to a Slice, passing a React component or element as a prop, passing a Date or Map/Set object (not plain JSON-serializable), or spreading a large props object that accidentally includes functions.

Related errors


AI-assisted analysis of gatsbyjs/gatsby@8b06340921 (2026-08-13). Data as JSON: /api/errors/ba8cf2b8415769b1. Report an issue: GitHub.