Skip to content

[next.js] initialFormState and no fields rendered may cause state.values undefined #1923

Open

Description

@MartinCura

Describe the bug

Hi! Great library you have here. I've been using it for while now and first time i've come across this.

In the Next.js App Router guide (https://tanstack.com/form/latest/docs/framework/react/guides/ssr#app-router-integration) it recommends to set the initial server state with

import { initialFormState } from '@tanstack/react-form-nextjs'

// inside component:
  const [formState, action] = useActionState(someAction, initialFormState)
  // ...
  const form = useForm({
    transform: useTransform((baseForm) => mergeForm(baseForm, formState ?? {}), [formState]),
    // ...

but initialFormState as defined has values: undefined (see:

)

This means that trying to access state.values.<field> will break as values is now undefined. In my case this cropped up trying to use <form.Subscribe>

Your minimal, reproducible example

None, sorry

Steps to reproduce

  1. Clone https://github.com/MartinCura/tanstack-form-1923
  2. pnpm i && pnpm run dev
  3. Go to http://localhost:3000, reload page

Expected behavior

I expect values to always be defined, as should all of the fields in my schema.

The bug is in application code! ...but following the docs' recommendations 🤔, and using initialFormState which introduces the issue.

How often does this bug happen?

Often

Screenshots or Videos

No response

Platform

  • Fedora
  • Firefox / Zen

TanStack Form adapter

None

TanStack Form version

v1.27.1

TypeScript version

v5.9.3

Additional context

I'm not sure if this is a docs issue instead of any type of bug, i'll leave it up to you!

I'd say the bottom line is not sure why the values should be allowed to be undefined, and thus if either initialFormState should be something that adapts to the form schema, or outright don't recommend it and make the user write it manually, maybe copying the default values (which is more or less the fix i implemented).

Activity

  1. MartinCura commented on Dec 8, 2025

    @MartinCura
    Author

    Wait i've done a minimal repro and i can't reproduce 🤔 investigating...

  2. MartinCura commented on Dec 8, 2025

    @MartinCura
    Author

    Is the recommendation now to use the specific package @tanstack/react-form-nextjs for everything? I see it re-exports everything from @tanstack/react-form

  3. MartinCura commented on Dec 8, 2025

    @MartinCura
    Author

    Ok i think i'm pinning it down:

    If there's a <form.Field> for a field, any field of the form, then it somehow ammends the values (even if it doesn't render anything itself).

    In my case i have an <Activity mode={isSubmitSuccessful ? "visible" : "hidden"> wrapping the only field, which means no fields are being rendered on the first pass. If i either add another <form.AppField> that always renders or if i hide the field with CSS instead, then no error is thrown.

    I'll upload a repro, clearly it was the correct path.

  4. MartinCura commented on Dec 8, 2025

    @MartinCura
    Author

    https://github.com/MartinCura/tanstack-form-1923

    just look at the client-component.tsx

    the first commit is a copy of the base example, except for package upgrades that leaked in there

  5. changed the title [-][next.js] `initialFormState` breaks Subscribe components if merging as in SSR guide[/-] [+][next.js] `initialFormState` and no fields rendered may cause `state.values` undefined[/+] on Dec 8, 2025
  6. MartinCura commented on Dec 8, 2025

    @MartinCura
    Author

    So leaving that investigation here, hope it's useful, luckily it's clear that i can workaround this issue by always having some field rendered since the first pass.

  7. crutchcorn commented on Dec 8, 2025

    @crutchcorn
    Contributor

    I suspect this work on my end may fix issues here:

    #1890

    But I could be wrong. Will validate later

  8. MartinCura commented on Dec 9, 2025

    @MartinCura
    Author

    I suspect this work on my end may fix issues here:

    #1890

    But I could be wrong. Will validate later

    Interesting, thank you for the quick answer!

    It may be of interest that console.log'ing i see

    • server-side: values defined
    • client-side: values first defined then undefined
    Image

    No hurry here, and do tell me if i can give a hand in debugging.

  9. MartinCura commented on Mar 2, 2026

    @MartinCura
    Author

    Goddammit i put Claude to investigate a strange bug and it linked it... to my own GitHub issue 😅

    Image
  10. MartinCura commented on Mar 2, 2026

    @MartinCura
    Author

    I am now having this problem more often, maybe because i've turned on Next.js' cacheComponents (https://nextjs.org/docs/app/getting-started/cache-components) and now many more things are wrapped in <Activity>. Has any solution cropped up since i posted this? Weird that no one else is bumping against this. I've already updated to the latest Tanstack Form versions.

  11. MartinCura commented on Mar 2, 2026

    @MartinCura
    Author

    In the meantime, Opus came up with using an alternative initialFormState as a workaround:

    /**
     * Drop-in replacement for `initialFormState` from `@tanstack/react-form-nextjs`.
     * The upstream version includes `values: undefined`, which causes `mergeForm` /
     * `mutateMergeDeep` to overwrite the real form values with `undefined`.
     * This is especially problematic when Next.js wraps routes in `<Activity>` (cache
     * components / PPR), since no `<Field>` may be mounted on the first render pass.
     * See: https://github.com/TanStack/form/issues/1923
     */
    export const initialFormState = {
      errorMap: { onServer: undefined },
      errors: [],
      // IMPORTANT: values must be `{}` not `undefined`. The upstream `initialFormState`
      // uses `undefined`, which causes `mutateMergeDeep` to overwrite the real form
      // values with `undefined` — crashing any `Subscribe` selector that reads `state.values`.
      values: {},
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } as ServerFormState<any, undefined>

    Not sure its logic is completely correct but it does solve the runtime issue for me and i guess the final type assert makes everything behave as before. Of course if we can come up with a sane fix instead of this i'll update :)

  12. added
    v1This issue has been created during v1 development.
    v2: needs investigationThis hasn't been confirmed or denied in v2 yet.
    on Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    v1This issue has been created during v1 development.v2: needs investigationThis hasn't been confirmed or denied in v2 yet.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions