form icon indicating copy to clipboard operation
form copied to clipboard

Array subfields missing errors in fieldMeta

Open juanvilladev opened this issue 9 months ago • 8 comments

Describe the bug

When a user pushes a field using field.pushValue or form.pushFieldValue, errors for the subfields are missing from fieldMeta.

This leads to a really bad state if the new subfield has errors on the form level schema. canSubmit becomes false so they can't submit the form, yet the error cannot be surfaced.

Your minimal, reproducible example

https://stackblitz.com/edit/tanstack-form-lntbeysv?file=src%2Findex.tsx

Steps to reproduce

  1. Add a row
  2. Notice canSubmit is now false, yet no error is surfaced
  3. Click "Log all errors" notice that the form has the errors, but is missing from the fieldMeta

Expected behavior

In the UI, I would expect the error is immediately surfaced to the user.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

See StackBlitz, latest version of TSF, valid TS version

TanStack Form adapter

react-form

TanStack Form version

^1.7.0

TypeScript version

No response

Additional context

This happens because we run the validator before the new pushed subfields mount. Since they have not mounted fieldMeta does not exist leading to the difference between the errorMap on the form and field level.

I propose that onMount we always check if the form errorMap contains errors for the field. If so, copy it over.

juanvilladev avatar Apr 27 '25 00:04 juanvilladev

@juanvilladev could you do me a massive favour? can you try this again with the latest version... theres a slight chance my latest commit might have fixed this as a side effect.

A very slight chance, but a slight chance at that... if not I'll have to investigate šŸ˜„

[edit] Just checked it myself, unfortunately not

harry-whorlow avatar May 08 '25 08:05 harry-whorlow

Hey, I wanted to ask what the status of the problem is, the error still exists and we can not display error messages on the arrays. (tested with 1.14.2)

rhupp-wps avatar Jul 24 '25 08:07 rhupp-wps

I’m also running into this same issue and am curious if there are any updates?

brandonleichty avatar Aug 01 '25 07:08 brandonleichty

If someone would be so kind to check the unit test I've wrote is testing for the expected behaviour, that would be a massive help to getting this fixed.

I'm on holiday atm so getting some conformation before starting the fix would be super appreciated šŸ˜„.

harry-whorlow avatar Aug 02 '25 10:08 harry-whorlow

I believe I am also seeing this issue if a form is validated before the FieldApi instance mounts in the DOM, regardless of explicit pushFieldValue behavior.

In my use case, certain form fields are rendered in a Tab Panel that is not mounted unless the user click on the Tab. The form still validates successfully and the unmounted field errors are present in the FormApi's error state as expected.

If the user then clicks on the Tab and the Tab Panel that contains the invalid fields is rendered, the FieldApi instances mount but they do not derive their FieldMeta from any existing FormApi state.

So the same de-sync issue arises where a field has errors in the FormApi error state but the FieldMeta does not reflect any issue.

dlindahl avatar Aug 13 '25 22:08 dlindahl

I'm running into the same problem. Is there an update yet?

christianklisch avatar Oct 16 '25 11:10 christianklisch

I also have this problem, which was quite the headache to figure out. Our application has multi-tab sections: Some fields are multilingual so we want the user to supply translations in all languages. I am trying to mark panel buttons as 'contains an issue' but sadly the field's meta does not exist until the panel is opened.

As a workaround, what would be the best way to programmatically 'mount' a field?

ThomasStock avatar Nov 17 '25 19:11 ThomasStock

I am currently solving the problem with useField({ form, name }) which seems to create the FieldApi for every field you use it for:

/**
 * In multi-tab forms or forms where not all fields are visibile / have mounted UI,
 *  the unmounted fields have no field meta and thus no error state on submit.
 * Tanstack form does not sync form-level errors to fields when they later get mounted, so those fields do not contain earlier errors.
 * Also, when we would want to check/count errors in a unrendered tab, we cannot loop over these fields' meta until the tab has been opened.
 * Solution:
 * We force-mount the fields by using useField. This ensures that the fields are always mounted and have errors in their meta.
 * Todo: reevaluate this once tanstack syncs form-level errors to unmounted fields
 * https://github.com/TanStack/form/issues/1630
 * https://github.com/TanStack/form/issues/1460
 */
function FieldEnsurer({ form, name }: { form: AnyFormApi; name: string }) {
  useField({ form, name });
  return null;
}

Then, where I render the tab-row containing fields for each language, I do:

{
  // Force mount all fields to ensure they have errors in their meta
}
{languages.map((language) =>
  getFieldKeysForLanguage(language).map((key) => (
    <FieldEnsurer key={key} form={form} name={key} />
  )),
)}

<TranslationEditor.TabsList>
  {languages.map((language) => {
    return (
      <form.Subscribe
        key={language}
        selector={({ fieldMeta }) =>
          getFieldKeysForLanguage(language).some(
            (key) => fieldMeta[key]?.errors?.length,
          )
        }
        children={(hasErrorsInLanguage) => {
          return (
            <TranslationEditor.TabTrigger
              key={language}
              language={language}
              error={hasErrorsInLanguage}
            />
          );
        }}
      />
    );
  })}
</TranslationEditor.TabsList>

ThomasStock avatar Nov 18 '25 11:11 ThomasStock